Index: lams_build/lib/lams/lams-central.jar =================================================================== diff -u -r56e7c366e4045f49252ac90762dd467bb2eb0a2d -r1c42119baf51e12d0ef19919cb5a266a186d4b7d Binary files differ Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r56e7c366e4045f49252ac90762dd467bb2eb0a2d -r1c42119baf51e12d0ef19919cb5a266a186d4b7d Binary files differ Index: lams_central/src/java/org/lamsfoundation/lams/rest/RestTags.java =================================================================== diff -u -rcc603dd74ff178c24fb743f0dc61d6a4b8389946 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/src/java/org/lamsfoundation/lams/rest/RestTags.java (.../RestTags.java) (revision cc603dd74ff178c24fb743f0dc61d6a4b8389946) +++ lams_central/src/java/org/lamsfoundation/lams/rest/RestTags.java (.../RestTags.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -52,6 +52,8 @@ public static String SUBMISSION_DEADLINE = "submissionDeadline"; public static String ALLOW_RICH_TEXT_EDITOR = "allowRichEditor"; public static String USE_SELECT_LEADER_TOOL_OUTPUT = "useSelectLeaderToolOuput"; + public static String MINIMUM_RATES = "minimumRates"; + public static String MAXIMUM_RATES = "maximumRates"; public static String QUESTIONS = "questions"; public static String QUESTION_TEXT = "questionText"; Index: lams_central/src/java/org/lamsfoundation/lams/web/RatingServlet.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/src/java/org/lamsfoundation/lams/web/RatingServlet.java (.../RatingServlet.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_central/src/java/org/lamsfoundation/lams/web/RatingServlet.java (.../RatingServlet.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -24,16 +24,21 @@ package org.lamsfoundation.lams.web; import java.io.IOException; +import java.text.NumberFormat; +import java.util.Locale; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.log4j.Logger; import org.apache.tomcat.util.json.JSONException; import org.apache.tomcat.util.json.JSONObject; -import org.lamsfoundation.lams.rating.dto.RatingDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; +import org.lamsfoundation.lams.rating.model.RatingCriteria; import org.lamsfoundation.lams.rating.service.RatingService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.WebUtil; @@ -57,29 +62,54 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + JSONObject JSONObject = new JSONObject(); getRatingService(); - float rating = Float.parseFloat((String) request.getParameter("rate")); String objectId = WebUtil.readStrParam(request, "idBox"); Long ratingCriteriaId = Long.parseLong(objectId.split("-")[0]); Long itemId = Long.parseLong(objectId.split("-")[1]); + RatingCriteria criteria = ratingService.getCriteriaByCriteriaId(ratingCriteriaId); + UserDTO user = (UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER); Integer userId = user.getUserID(); - RatingDTO averageRatingDTO = ratingService.rateItem(ratingCriteriaId, userId, itemId, rating); + // get rating value as either float or comment String + try { + if (criteria.isCommentsEnabled()) { + String comment = WebUtil.readStrParam(request, "comment"); + ratingService.commentItem(criteria, userId, itemId, comment); + JSONObject.put("comment", StringEscapeUtils.escapeCsv(comment)); - // refresh numOfRatings - // int numOfRatings = ratingService.getNumOfRatingsByUserAndForum(userUid, forumUid); + } else { + float rating = Float.parseFloat((String) request.getParameter("rate")); - JSONObject JSONObject = new JSONObject(); - try { - JSONObject.put("averageRating", averageRatingDTO.getAverageRating()); - JSONObject.put("numberOfVotes", averageRatingDTO.getNumberOfVotes()); + + ItemRatingCriteriaDTO averageRatingDTO = ratingService.rateItem(criteria, userId, itemId, rating); + + NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); + numberFormat.setMaximumFractionDigits(1); + JSONObject.put("userRating", numberFormat.format(rating)); + JSONObject.put("averageRating", averageRatingDTO.getAverageRating()); + JSONObject.put("numberOfVotes", averageRatingDTO.getNumberOfVotes()); + } + + boolean hasRatingLimits = WebUtil.readBooleanParam(request, "hasRatingLimits", false); + + // refresh countRatedItems in case there is rating limit set + if (hasRatingLimits) { + // as long as this can be requested only for LEARNER_ITEM_CRITERIA_TYPE type, cast Criteria + LearnerItemRatingCriteria learnerItemRatingCriteria = (LearnerItemRatingCriteria) criteria; + Long toolContentId = learnerItemRatingCriteria.getToolContentId(); + + int countRatedItems = ratingService.getCountItemsRatedByUser(toolContentId, userId); + JSONObject.put("countRatedItems", countRatedItems); + } + } catch (JSONException e) { throw new ServletException(e); } - // JSONObject.put("numOfRatings", numOfRatings); + response.setContentType("application/json;charset=utf-8"); response.getWriter().print(JSONObject); } Index: lams_central/web/WEB-INF/web.xml =================================================================== diff -u -r99bad81dae364803715e125f14aedb605196b30c -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/web/WEB-INF/web.xml (.../web.xml) (revision 99bad81dae364803715e125f14aedb605196b30c) +++ lams_central/web/WEB-INF/web.xml (.../web.xml) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -433,6 +433,13 @@ org.lamsfoundation.lams.web.OrganisationGroupServlet + + + RatingServlet + + org.lamsfoundation.lams.web.RatingServlet + + LearningDesignRestServlet @@ -513,6 +520,11 @@ CourseGroupManager /services/CourseGroupManager + + + RatingServlet + /servlet/rateItem + updateCollapsedGroup Index: lams_central/web/css/jquery.jRating.css =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/web/css/jquery.jRating.css (.../jquery.jRating.css) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_central/web/css/jquery.jRating.css (.../jquery.jRating.css) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -47,9 +47,35 @@ } /** Please, note this is a LAMS customization. In case of library upgrade copy these lines manually. **/ -.rating-stars-holder {width: 150px; text-align: center;} +.extra-controls-inner:after { + content: " "; + display: block; + height: 0; + clear: both; +} +.rating-stars-holder {width: 150px; text-align: center; float: right;} .rating-stars-caption {padding-top: 6px;} -.rating-stars, .rating-stars-disabled {margin: 0px auto;} +.rating-stars, .rating-stars-disabled {margin: 0px auto; min-height: 20px;} +.add-comment { + background-image: url('../images/tick.png'); + width:16px; + height:16px; + cursor: pointer; + float: right; + margin-top: 20px; +} +.rating-comment{ + background: url("../images/css/greyfade_bg.jpg") repeat-x scroll 0px 0px transparent; + padding: 15px; + margin: 10px 0; +} +.rating-info{ + margin-top: 0; + margin-bottom: 12px; +} +textarea[id^=comment-textarea-] { + color: #d3d3d3; +} /** Remove the following once we move all tools to use Rating.tag. **/ .rating-stars-div {float:right; padding-right: 10px; margin-top: -8px; min-height: 45px;} Index: lams_central/web/includes/javascript/common.js =================================================================== diff -u -r072bb60f4577c619051ad2bca23674a0c41d4856 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/web/includes/javascript/common.js (.../common.js) (revision 072bb60f4577c619051ad2bca23674a0c41d4856) +++ lams_central/web/includes/javascript/common.js (.../common.js) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -107,4 +107,16 @@ xmlhttp.open("POST", url, false); xmlhttp.send(); } + +function getNumberOfWords(value, isRemoveHtmlTags) { + + //HTML tags stripping + if (isRemoveHtmlTags) { + value = value.replace(/ /g, '').replace(/<\/?[a-z][^>]*>/gi, ''); + } + value = value.trim(); + + var wordCount = value ? (value.replace(/['";:,.?\-!]+/g, '').match(/\S+/g) || []).length : 0; + return wordCount; +} \ No newline at end of file Index: lams_central/web/includes/javascript/jquery.tablesorter-pager.js =================================================================== diff -u -ra1b4a3143714e2704412c585131a93fee2d8c40b -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/web/includes/javascript/jquery.tablesorter-pager.js (.../jquery.tablesorter-pager.js) (revision a1b4a3143714e2704412c585131a93fee2d8c40b) +++ lams_central/web/includes/javascript/jquery.tablesorter-pager.js (.../jquery.tablesorter-pager.js) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -1,2 +1,5 @@ -/* tablesorter (FORK) pager plugin updated 12/22/2014 (v2.18.4) */ -;(function(h){var k=h.tablesorter;h.extend({tablesorterPager:new function(){this.defaults={container:null,ajaxUrl:null,customAjaxUrl:function(c,a){return a},ajaxObject:{dataType:"json"},processAjaxOnInit:!0,ajaxProcessing:function(c){return[0,[],null]},output:"{startRow} to {endRow} of {totalRows} rows",updateArrows:!0,page:0,pageReset:0,size:10,maxOptionSize:20,savePages:!0,storageKey:"tablesorter-pager",fixedHeight:!1,countChildRows:!1,removeRows:!1,cssFirst:".first",cssPrev:".prev",cssNext:".next", cssLast:".last",cssGoto:".gotoPage",cssPageDisplay:".pagedisplay",cssPageSize:".pagesize",cssErrorRow:"tablesorter-errorRow",cssDisabled:"disabled",totalRows:0,totalPages:0,filteredRows:0,filteredPages:0,ajaxCounter:0,currentFilters:[],startRow:0,endRow:0,$size:null,last:{}};var x=this,v=function(c,a){var b=c.cssDisabled,e=!!a,f=e||0===c.page,g=Math.min(c.totalPages,c.filteredPages),e=e||c.page===g-1||0===g;c.updateArrows&&(c.$container.find(c.cssFirst+","+c.cssPrev)[f?"addClass":"removeClass"](b).attr("aria-disabled", f),c.$container.find(c.cssNext+","+c.cssLast)[e?"addClass":"removeClass"](b).attr("aria-disabled",e))},p=function(c,a){var b=c.config,e=b.$table.hasClass("hasFilters");e&&!a.ajaxUrl?h.isEmptyObject(b.cache)?a.filteredRows=a.totalRows=b.$tbodies.eq(0).children("tr").not(a.countChildRows?"":"."+b.cssChildRow).length:(a.filteredRows=0,h.each(b.cache[0].normalized,function(c,e){a.filteredRows+=a.regexRows.test(e[b.columns].$row[0].className)?0:1})):e||(a.filteredRows=a.totalRows)},t=function(c,a,b){if(!a.initializing){var e, f,g,l=c.config;e=a.size||10;a.countChildRows&&f.push(l.cssChildRow);a.totalPages=Math.ceil(a.totalRows/e);l.totalRows=a.totalRows;p(c,a);l.filteredRows=a.filteredRows;a.filteredPages=Math.ceil(a.filteredRows/e)||0;0<=Math.min(a.totalPages,a.filteredPages)&&(f=a.size*a.page>a.filteredRows&&b,a.startRow=f?1:0===a.filteredRows?0:a.size*a.page+1,a.page=f?0:a.page,a.endRow=Math.min(a.filteredRows,a.totalRows,a.size*(a.page+1)),g=a.$container.find(a.cssPageDisplay),e=(a.ajaxData&&a.ajaxData.output?a.ajaxData.output|| a.output:a.output).replace(/\{page([\-+]\d+)?\}/gi,function(d,b){return a.totalPages?a.page+(b?parseInt(b,10):1):0}).replace(/\{\w+(\s*:\s*\w+)?\}/gi,function(d){var b,c;b=d.replace(/[{}\s]/g,"");d=b.split(":");c=a.ajaxData;var e=/(rows?|pages?)$/i.test(b)?0:"";return/(startRow|page)/.test(d[0])&&"input"===d[1]?(b=(""+("page"===d[0]?a.totalPages:a.totalRows)).length,c="page"===d[0]?a.page+1:a.startRow,''):1'+b+""}),a.$goto.html(f).val(a.page+1)),g.find(".ts-startRow, .ts-page").unbind("change").bind("change",function(){var b=h(this).val(),b=h(this).hasClass("ts-startRow")?Math.floor(b/a.size)+1:b;l.$table.trigger("pageSet.pager",[b])})));v(a);D(c,a);a.initialized&&!1!==b&&(l.$table.trigger("pagerComplete",a),a.savePages&& k.storage&&k.storage(c,a.storageKey,{page:a.page,size:a.size}))}},I=function(c){var a,b,e,f,g;g=Math.min(c.totalPages,c.filteredPages)||1;var l=5*Math.ceil(g/c.maxOptionSize/5);e=g>c.maxOptionSize;f=c.page+1;a=l;b=g-l;var d=[1];for(a=e?l:1;a<=g;)d.push(a),a+=e?l:1;d.push(g);if(e){e=[];b=Math.max(Math.floor(c.maxOptionSize/l)-1,5);a=f-b;1>a&&(a=1);b=f+b;for(b>g&&(b=g);a<=b;a++)e.push(a);d=h.grep(d,function(a,b){return h.inArray(a,d)===b});f=d.length;g=e.length;f-g>l/2&&f+g>c.maxOptionSize&&(c=Math.floor(f/ 2)-Math.floor(g/2),Array.prototype.splice.apply(d,[c,g]));d=d.concat(e)}return d=h.grep(d,function(a,b){return h.inArray(a,d)===b}).sort(function(a,b){return a-b})},D=function(c,a){var b,e=c.config,f=e.$tbodies.eq(0);f.find("tr.pagerSavedHeightSpacer").remove();a.fixedHeight&&!a.isDisabled&&(b=h.data(c,"pagerSavedHeight"))&&(b-=f.height(),5'))},y=function(c,a){var b;b=c.config;var e=b.$tbodies.eq(0);e.find("tr.pagerSavedHeightSpacer").remove();e.children("tr:visible").length||e.append(' ');b=e.children("tr").eq(0).height()*a.size;h.data(c,"pagerSavedHeight",b);D(c,a);h.data(c,"pagerLastSize",a.size)},w=function(c,a){if(!a.ajaxUrl){var b,e=0,f=c.config,g=f.$tbodies.eq(0).children("tr"),h=g.length,d=a.page*a.size,m=d+a.size,u=f.widgetOptions&& f.widgetOptions.filter_filteredRow||"filtered",r=0;for(b=0;b=d&&r";for(f=0;f"+e[g][f]+"";n+=""}b.processAjaxOnInit&&q.$tbodies.eq(0).html(n)}b.processAjaxOnInit=!0;u&&u.length===c&&(m=(l=p.hasClass("hasStickyHeaders"))? q.widgetOptions.$sticky.children("thead:first").children("tr").children():"",d=p.find("tfoot tr:first").children(),q.$headers.filter("th").each(function(a){var b=h(this),c;b.find("."+k.css.icon).length?(c=b.find("."+k.css.icon).clone(!0),b.find(".tablesorter-header-inner").html(u[a]).append(c),l&&m.length&&(c=m.eq(a).find("."+k.css.icon).clone(!0),m.eq(a).find(".tablesorter-header-inner").html(u[a]).append(c))):(b.find(".tablesorter-header-inner").html(u[a]),l&&m.length&&m.eq(a).find(".tablesorter-header-inner").html(u[a])); d.eq(a).html(u[a])}))}q.showProcessing&&k.isProcessing(a);b.totalPages=Math.ceil(b.totalRows/(b.size||10));b.last.totalRows=b.totalRows;b.last.currentFilters=b.currentFilters;b.last.sortList=(q.sortList||[]).join(",");t(a,b,!0);p.trigger("updateCache",[function(){b.initialized&&setTimeout(function(){p.trigger("applyWidgets").trigger("pagerChange",b)},0)}])}b.initialized||(b.initialized=!0,b.initializing=!1,h(a).trigger("applyWidgets").trigger("pagerInitialized",b),t(a,b))},K=function(c,a){var b=J(c, a),e=h(document),f,g=c.config;""!==b&&(g.showProcessing&&k.isProcessing(c,!0),e.bind("ajaxError.pager",function(b,d,f,g){F(null,c,a,d,g);e.unbind("ajaxError.pager")}),f=++a.ajaxCounter,a.last.ajaxUrl=b,a.ajaxObject.url=b,a.ajaxObject.success=function(b,d,g){f(a&&a.length||0))e.debug&&k.log("Pager: no rows for pager to render");else{b.page>=b.totalPages&&z(c,b);b.isDisabled=!1;b.initialized&&d.trigger("pagerChange",b);if(b.removeRows){k.clearTableBody(c);e=k.processTbody(c,e.$tbodies.eq(0), !0);f=m?0:p;g=m?0:p;for(l=0;lp&&l<=r&&(l++,e.append(a[f]))),f++;k.processTbody(c,e,!1)}else w(c,b);t(c,b);c.isUpdating&&d.trigger("updateComplete",[c,!0])}},G=function(c,a){a.ajax?v(a,!0):(a.isDisabled=!0,h.data(c,"pagerLastPage",a.page),h.data(c,"pagerLastSize",a.size),a.page=0,a.size=a.totalRows,a.totalPages=1,h(c).addClass("pagerDisabled").removeAttr("aria-describedby").find("tr.pagerSavedHeightSpacer").remove(),A(c,c.config.rowsCopy, a),h(c).trigger("applyWidgets"),c.config.debug&&k.log("pager disabled"));a.$size.add(a.$goto).add(a.$container.find(".ts-startRow, .ts-page")).each(function(){h(this).attr("aria-disabled","true").addClass(a.cssDisabled)[0].disabled=!0})},B=function(c){var a=c.config,b=a.pager;a.$table.trigger("updateCache",[function(){var e,f=[],g=c.config.cache[0].normalized;b.totalRows=g.length;for(e=0;ea.page&&(a.page=0),a.page>e-1&&0!==e&&(a.page=e-1),l.currentFilters=""===(l.currentFilters||[]).join("")?[]:l.currentFilters,a.currentFilters=""===(a.currentFilters||[]).join("")?[]:a.currentFilters,l.page!==a.page||l.size!==a.size||l.totalRows!==a.totalRows||(l.currentFilters||[]).join(",")!== (a.currentFilters||[]).join(",")||(l.ajaxUrl||"")!==(a.ajaxObject.url||"")||(l.optAjaxUrl||"")!==(a.ajaxUrl||"")||l.sortList!==(f.sortList||[]).join(","))f.debug&&k.log("Pager changing to page "+a.page),a.last={page:a.page,size:a.size,sortList:(f.sortList||[]).join(","),totalRows:a.totalRows,currentFilters:a.currentFilters||[],ajaxUrl:a.ajaxObject.url||"",optAjaxUrl:a.ajaxUrl||""},a.ajax?K(c,a):a.ajax||A(c,f.rowsCopy,a),h.data(c,"pagerLastPage",a.page),a.initialized&&!1!==b&&(g.trigger("pageMoved", a).trigger("applyWidgets"),c.isUpdating&&g.trigger("updateComplete",[c,!0]))}},C=function(c,a,b){b.size=a||b.size||10;b.$size.val(b.size);h.data(c,"pagerLastPage",b.page);h.data(c,"pagerLastSize",b.size);b.totalPages=Math.ceil(b.totalRows/b.size);b.filteredPages=Math.ceil(b.filteredRows/b.size);n(c,b)},L=function(c,a){a.page=0;n(c,a)},z=function(c,a){a.page=Math.min(a.totalPages,a.filteredPages)-1;n(c,a)},M=function(c,a){a.page++;a.page>=Math.min(a.totalPages,a.filteredPages)-1&&(a.page=Math.min(a.totalPages, a.filteredPages)-1);n(c,a)},N=function(c,a){a.page--;0>=a.page&&(a.page=0);n(c,a)},H=function(c,a,b){var e,f=c.config;a.$size.add(a.$goto).add(a.$container.find(".ts-startRow, .ts-page")).removeClass(a.cssDisabled).removeAttr("disabled").attr("aria-disabled","false");a.isDisabled=!1;a.page=h.data(c,"pagerLastPage")||a.page||0;a.size=h.data(c,"pagerLastSize")||parseInt(a.$size.find("option[selected]").val(),10)||a.size||10;a.$size.val(a.size);a.totalPages=Math.ceil(Math.min(a.totalRows,a.filteredRows)/ a.size);c.id&&(e=c.id+"_pager_info",a.$container.find(a.cssPageDisplay).attr("id",e),f.$table.attr("aria-describedby",e));y(c,a);b&&(f.$table.trigger("updateRows"),C(c,a.size,a),E(c,a),f.debug&&k.log("pager enabled"))};x.appender=function(c,a){var b=c.config,e=b.pager;e.ajax||(b.rowsCopy=a,e.totalRows=e.countChildRows?b.$tbodies.eq(0).children("tr").length:a.length,e.size=h.data(c,"pagerLastSize")||e.size||10,e.totalPages=Math.ceil(e.totalRows/e.size),A(c,a,e),t(c,e,!1))};x.construct=function(c){return this.each(function(){if(this.config&& this.hasInitialized){var a,b,e,f=this,g=f.config,l=g.widgetOptions,d=g.pager=h.extend(!0,{},h.tablesorterPager.defaults,c),m=g.$table,p=d.$container=h(d.container).addClass("tablesorter-pager").show();g.debug&&k.log("Pager initializing");d.oldAjaxSuccess=d.oldAjaxSuccess||d.ajaxObject.success;g.appender=x.appender;d.initializing=!0;d.savePages&&k.storage&&(a=k.storage(f,d.storageKey)||{},d.page=isNaN(a.page)?d.page:a.page,d.size=(isNaN(a.size)?d.size:a.size)||10,h.data(f,"pagerLastSize",d.size)); d.regexRows=new RegExp("("+(l.filter_filteredRow||"filtered")+"|"+g.selectorRemove.slice(1)+"|"+g.cssChildRow+")");m.unbind("filterInit filterStart filterEnd sortEnd disable enable destroy updateComplete pageSize pageSet ".split(" ").join(".pager ")).bind("filterInit.pager filterStart.pager",function(a){d.currentFilters=g.$table.data("lastSearch");"filterStart"===a.type&&!1!==d.pageReset&&(g.lastCombinedFilter||"")!==(d.currentFilters||[]).join("")&&(d.page=d.pageReset)}).bind("filterEnd.pager sortEnd.pager", function(){d.currentFilters=g.$table.data("lastSearch");if(d.initialized||d.initializing)g.delayInit&&g.rowsCopy&&0===g.rowsCopy.length&&B(f),t(f,d,!1),n(f,d,!1),g.$table.trigger("applyWidgets")}).bind("disable.pager",function(a){a.stopPropagation();G(f,d)}).bind("enable.pager",function(a){a.stopPropagation();H(f,d,!0)}).bind("destroy.pager",function(a){a.stopPropagation();G(f,d);d.$container.hide();f.config.appender=null;d.initialized=!1;delete f.config.rowsCopy;h(f).unbind("filterInit filterStart filterEnd sortEnd disable enable destroy updateComplete pageSize pageSet ".split(" ").join(".pager ")); k.storage&&k.storage(f,d.storageKey,"")}).bind("updateComplete.pager",function(a,b,c){a.stopPropagation();b&&!c&&(a=g.$tbodies.eq(0).children("tr").not(g.selectorRemove),d.totalRows=a.length-(d.countChildRows?0:a.filter("."+g.cssChildRow).length),d.totalPages=Math.ceil(d.totalRows/d.size),a.length&&g.rowsCopy&&0===g.rowsCopy.length&&B(b),d.page>=d.totalPages&&z(b,d),w(b,d),y(b,d),t(b,d,!0))}).bind("pageSize.pager",function(a,b){a.stopPropagation();C(f,parseInt(b,10)||10,d);w(f,d);t(f,d,!1);d.$size.length&& d.$size.val(d.size)}).bind("pageSet.pager",function(a,b){a.stopPropagation();d.page=(parseInt(b,10)||1)-1;d.$goto.length&&d.$goto.val(d.size);n(f,d,!0);t(f,d,!1)});b=[d.cssFirst,d.cssPrev,d.cssNext,d.cssLast];e=[L,N,M,z];p.find(b.join(",")).attr("tabindex",0).unbind("click.pager").bind("click.pager",function(a){a.stopPropagation();var c=h(this),g=b.length;if(!c.hasClass(d.cssDisabled))for(a=0;a/.test(v)?h(v):h(''+v+"")).click(function(){h(this).remove()}).appendTo(k.$table.find("thead:first")).addClass(t+" "+k.selectorRemove.slice(1)).attr({role:"alert","aria-live":"assertive"}))})};h.fn.extend({tablesorterPager:h.tablesorterPager.construct})})(jQuery); +/*! + * tablesorter (FORK) pager plugin + * updated 5/17/2015 (v2.22.0) + */ +!function(a){"use strict";var b=a.tablesorter;a.extend({tablesorterPager:new function(){this.defaults={container:null,ajaxUrl:null,customAjaxUrl:function(a,b){return b},ajaxObject:{dataType:"json"},processAjaxOnInit:!0,ajaxProcessing:function(a){return[0,[],null]},output:"{startRow} to {endRow} of {totalRows} rows",updateArrows:!0,page:0,pageReset:0,size:10,maxOptionSize:20,savePages:!0,storageKey:"tablesorter-pager",fixedHeight:!1,countChildRows:!1,removeRows:!1,cssFirst:".first",cssPrev:".prev",cssNext:".next",cssLast:".last",cssGoto:".gotoPage",cssPageDisplay:".pagedisplay",cssPageSize:".pagesize",cssErrorRow:"tablesorter-errorRow",cssDisabled:"disabled",totalRows:0,totalPages:0,filteredRows:0,filteredPages:0,ajaxCounter:0,currentFilters:[],startRow:0,endRow:0,$size:null,last:{}};var c="filterInit filterStart filterEnd sortEnd disable enable destroy updateComplete pageSize pageSet pageAndSize pagerUpdate refreshComplete ",d=this,e=function(a,b){var c="addClass",d="removeClass",e=a.cssDisabled,f=!!b,g=f||0===a.page,h=Math.min(a.totalPages,a.filteredPages),i=f||a.page===h-1||0===h;a.updateArrows&&(a.$container.find(a.cssFirst+","+a.cssPrev)[g?c:d](e).attr("aria-disabled",g),a.$container.find(a.cssNext+","+a.cssLast)[i?c:d](e).attr("aria-disabled",i))},f=function(b,c){var d,e,f,g=b.config,h=g.$table.hasClass("hasFilters");if(h&&!c.ajaxUrl)if(a.isEmptyObject(g.cache))c.filteredRows=c.totalRows=g.$tbodies.eq(0).children("tr").not(c.countChildRows?"":"."+g.cssChildRow).length;else for(c.filteredRows=0,d=g.cache[0].normalized,f=d.length,e=0;f>e;e++)c.filteredRows+=c.regexRows.test(d[e][g.columns].$row[0].className)?0:1;else h||(c.filteredRows=c.totalRows)},g=function(c,d,g){if(!d.initializing){var j,k,l,m,n,o,p=c.config,q=d.size||d.settings.size||10;if(d.countChildRows&&k.push(p.cssChildRow),d.totalPages=Math.ceil(d.totalRows/q),p.totalRows=d.totalRows,f(c,d),p.filteredRows=d.filteredRows,d.filteredPages=Math.ceil(d.filteredRows/q)||0,Math.min(d.totalPages,d.filteredPages)>=0){if(k=d.size*d.page>d.filteredRows&&g,d.page=k?d.pageReset||0:d.page,d.startRow=k?d.size*d.page+1:0===d.filteredRows?0:d.size*d.page+1,d.endRow=Math.min(d.filteredRows,d.totalRows,d.size*(d.page+1)),l=d.$container.find(d.cssPageDisplay),j=(d.ajaxData&&d.ajaxData.output?d.ajaxData.output||d.output:d.output).replace(/\{page([\-+]\d+)?\}/gi,function(a,b){return d.totalPages?d.page+(b?parseInt(b,10):1):0}).replace(/\{\w+(\s*:\s*\w+)?\}/gi,function(a){var b,c,e=a.replace(/[{}\s]/g,""),f=e.split(":"),g=d.ajaxData,h=/(rows?|pages?)$/i.test(e)?0:"";return/(startRow|page)/.test(f[0])&&"input"===f[1]?(b=(""+("page"===f[0]?d.totalPages:d.totalRows)).length,c="page"===f[0]?d.page+1:d.startRow,''):f.length>1&&g&&g[f[0]]?g[f[0]][f[1]]:d[e]||(g?g[e]:h)||h}),d.$goto.length){for(k="",o=h(d),n=o.length,m=0;n>m;m++)k+='";d.$goto.html(k).val(d.page+1)}l.length&&(l["INPUT"===l[0].nodeName?"val":"html"](j),l.find(".ts-startRow, .ts-page").unbind("change.pager").bind("change.pager",function(){var b=a(this).val(),c=a(this).hasClass("ts-startRow")?Math.floor(b/d.size)+1:b;p.$table.trigger("pageSet.pager",[c])}))}e(d),i(c,d),d.initialized&&g!==!1&&(p.debug&&b.log("Pager: Triggering pagerComplete"),p.$table.trigger("pagerComplete",d),d.savePages&&b.storage&&b.storage(c,d.storageKey,{page:d.page,size:d.size}))}},h=function(b){var c,d,e,f,g,h,i=Math.min(b.totalPages,b.filteredPages)||1,j=5*Math.ceil(i/b.maxOptionSize/5),k=i>b.maxOptionSize,l=b.page+1,m=j,n=i-j,o=[1],p=k?j:1;for(c=p;i>=c;)o.push(c),c+=k?j:1;if(o.push(i),k){for(e=[],d=Math.max(Math.floor(b.maxOptionSize/j)-1,5),m=l-d,1>m&&(m=1),n=l+d,n>i&&(n=i),c=m;n>=c;c++)e.push(c);o=a.grep(o,function(b,c){return a.inArray(b,o)===c}),g=o.length,h=e.length,g-h>j/2&&g+h>b.maxOptionSize&&(f=Math.floor(g/2)-Math.floor(h/2),Array.prototype.splice.apply(o,[f,h])),o=o.concat(e)}return o=a.grep(o,function(b,c){return a.inArray(b,o)===c}).sort(function(a,b){return a-b})},i=function(b,c){var d,e,f=b.config,g=f.$tbodies.eq(0);g.find("tr.pagerSavedHeightSpacer").remove(),c.fixedHeight&&!c.isDisabled&&(e=a.data(b,"pagerSavedHeight"),e&&(d=e-g.height(),d>5&&a.data(b,"pagerLastSize")===c.size&&g.children("tr:visible").length')))},j=function(b,c){var d,e=b.config,f=e.$tbodies.eq(0);f.find("tr.pagerSavedHeightSpacer").remove(),f.children("tr:visible").length||f.append(' '),d=f.children("tr").eq(0).height()*c.size,a.data(b,"pagerSavedHeight",d),i(b,c),a.data(b,"pagerLastSize",c.size)},k=function(a,c){if(!c.ajaxUrl){var d,e=0,f=a.config,g=f.$tbodies.eq(0).children("tr"),h=g.length,i=c.page*c.size,j=i+c.size,k=f.widgetOptions&&f.widgetOptions.filter_filteredRow||"filtered",l=0,m=0;for(c.cacheIndex=[],d=0;h>d;d++)g[d].className.match(k)||(m===i&&g[d].className.match(f.cssChildRow)?g[d].style.display="none":(g[d].style.display=m>=i&&j>m?"":"none",l!==m&&m>=i&&j>m&&(c.cacheIndex.push(d),l=m),m+=g[d].className.match(f.cssChildRow+"|"+f.selectorRemove.slice(1))&&!c.countChildRows?0:1,m===j&&"none"!==g[d].style.display&&g[d].className.match(b.css.cssHasChild)&&(e=d)));if(e>0&&g[e].className.match(b.css.cssHasChild))for(;++e> Ajax Error",f,h),b.showError(d,0===f.status?"Not connected, verify Network":404===f.status?"Requested page not found [404]":500===f.status?"Internal Server Error [500]":"parsererror"===h?"Requested JSON parse failed":"timeout"===h?"Time out error":"abort"===h?"Ajax Request aborted":"Uncaught error: "+f.statusText+" ["+f.status+"]"),w.$tbodies.eq(0).children("tr").detach(),e.totalRows=0;else{if(a.isArray(z)?(k=isNaN(z[0])&&!isNaN(z[1]),u=z[k?1:0],e.totalRows=isNaN(u)?e.totalRows||0:u,w.totalRows=w.filteredRows=e.filteredRows=e.totalRows,s=0===e.totalRows?[""]:z[k?0:1]||[],r=z[2]):(e.ajaxData=z,w.totalRows=e.totalRows=z.total,w.filteredRows=e.filteredRows="undefined"!=typeof z.filteredRows?z.filteredRows:z.total,r=z.headers,s=z.rows),t=s&&s.length,s instanceof jQuery)e.processAjaxOnInit&&(w.$tbodies.eq(0).children("tr").detach(),w.$tbodies.eq(0).append(s));else if(t){for(i=0;t>i;i++){for(y+="",j=0;j"+s[i][j]+"";y+=""}e.processAjaxOnInit&&w.$tbodies.eq(0).html(y)}if(e.processAjaxOnInit=!0,r&&r.length===A)for(l=x.hasClass("hasStickyHeaders"),n=l?w.widgetOptions.$sticky.children("thead:first").children("tr").children():"",m=x.find("tfoot tr:first").children(),o=w.$headers.filter("th "),v=o.length,j=0;v>j;j++)p=o.eq(j),p.find("."+b.css.icon).length?(q=p.find("."+b.css.icon).clone(!0),p.find(".tablesorter-header-inner").html(r[j]).append(q),l&&n.length&&(q=n.eq(j).find("."+b.css.icon).clone(!0),n.eq(j).find(".tablesorter-header-inner").html(r[j]).append(q))):(p.find(".tablesorter-header-inner").html(r[j]),l&&n.length&&n.eq(j).find(".tablesorter-header-inner").html(r[j])),m.eq(j).html(r[j])}w.showProcessing&&b.isProcessing(d),e.totalPages=Math.ceil(e.totalRows/(e.size||e.settings.size||10)),e.last.totalRows=e.totalRows,e.last.currentFilters=e.currentFilters,e.last.sortList=(w.sortList||[]).join(","),g(d,e,!1),x.trigger("updateCache",[function(){e.initialized&&setTimeout(function(){w.debug&&b.log("Pager: Triggering pagerChange"),x.trigger("applyWidgets").trigger("pagerChange",e),g(d,e,!0)},0)}])}e.initialized||(e.initialized=!0,e.initializing=!1,d.config.debug&&b.log("Pager: Triggering pagerInitialized"),a(d).trigger("applyWidgets").trigger("pagerInitialized",e),g(d,e))},n=function(c,d){var e,f=o(c,d),g=a(document),h=c.config;""!==f&&(h.showProcessing&&b.isProcessing(c,!0),g.bind("ajaxError.pager",function(a,b,e,f){m(null,c,d,b,f),g.unbind("ajaxError.pager")}),e=++d.ajaxCounter,d.last.ajaxUrl=f,d.ajaxObject.url=f,d.ajaxObject.success=function(a,b,f){ee;e++)m.push(k+"["+i[e][0]+"]="+i[e][1]);h=h.replace(/\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/g,m.length?m.join("&"):k),m=[]}if(l){for(l=l[1],f=j.length,e=0;f>e;e++)j[e]&&m.push(l+"["+e+"]="+encodeURIComponent(j[e]));h=h.replace(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g,m.length?m.join("&"):l),d.currentFilters=j}return"function"==typeof d.customAjaxUrl&&(h=d.customAjaxUrl(c,h)),g.debug&&b.log("Pager: Ajax url = "+h),h},p=function(c,d,e){var f,h,i,j,l=a(c),m=c.config,n=m.$table.hasClass("hasFilters"),o=d&&d.length||0,p=e.page*e.size,q=e.size;if(1>o)return void(m.debug&&b.log("Pager: >> No rows for pager to render"));if(e.page>=e.totalPages&&v(c,e),e.cacheIndex=[],e.isDisabled=!1,e.initialized&&(m.debug&&b.log("Pager: Triggering pagerChange"),l.trigger("pagerChange",e)),e.removeRows){for(b.clearTableBody(c),f=b.processTbody(c,m.$tbodies.eq(0),!0),h=n?0:p,i=n?0:p,j=0;q>j&&hp&&q>=j&&(j++,e.cacheIndex.push(h),f.append(d[h]))),h++;b.processTbody(c,f,!1)}else k(c,e);g(c,e),c.isUpdating&&(m.debug&&b.log("Pager: Triggering updateComplete"),l.trigger("updateComplete",[c,!0]))},q=function(c,d){var f,g,h;for(d.ajax?e(d,!0):(d.isDisabled=!0,a.data(c,"pagerLastPage",d.page),a.data(c,"pagerLastSize",d.size),d.page=0,d.size=d.totalRows,d.totalPages=1,a(c).addClass("pagerDisabled").removeAttr("aria-describedby").find("tr.pagerSavedHeightSpacer").remove(),p(c,c.config.rowsCopy,d),a(c).trigger("applyWidgets"),c.config.debug&&b.log("Pager: Disabled")),g=d.$size.add(d.$goto).add(d.$container.find(".ts-startRow, .ts-page")),h=g.length,f=0;h>f;f++)g.eq(f).attr("aria-disabled","true").addClass(d.cssDisabled)[0].disabled=!0},r=function(a){var b=a.config,c=b.pager;b.$table.trigger("updateCache",[function(){var d,e=[],f=a.config.cache[0].normalized;for(c.totalRows=f.length,d=0;dg-1&&0!==g&&(d.page=g-1),j.currentFilters=""===(j.currentFilters||[]).join("")?[]:j.currentFilters,d.currentFilters=""===(d.currentFilters||[]).join("")?[]:d.currentFilters,(j.page!==d.page||j.size!==d.size||j.totalRows!==d.totalRows||(j.currentFilters||[]).join(",")!==(d.currentFilters||[]).join(",")||(j.ajaxUrl||"")!==(d.ajaxObject.url||"")||(j.optAjaxUrl||"")!==(d.ajaxUrl||"")||j.sortList!==(h.sortList||[]).join(","))&&(h.debug&&b.log("Pager: Changing to page "+d.page),d.last={page:d.page,size:d.size,sortList:(h.sortList||[]).join(","),totalRows:d.totalRows,currentFilters:d.currentFilters||[],ajaxUrl:d.ajaxObject.url||"",optAjaxUrl:d.ajaxUrl||""},d.ajax?n(c,d):d.ajax||p(c,h.rowsCopy,d),a.data(c,"pagerLastPage",d.page),d.initialized&&e!==!1&&(h.debug&&b.log("Pager: Triggering pageMoved"),i.trigger("pageMoved",d).trigger("applyWidgets"),c.isUpdating&&(h.debug&&b.log("Pager: Triggering updateComplete"),i.trigger("updateComplete",[c,!0]))))))}},t=function(b,c,d){d.size=c||d.size||d.settings.size||10,d.$size.val(d.size),a.data(b,"pagerLastPage",d.page),a.data(b,"pagerLastSize",d.size),d.totalPages=Math.ceil(d.totalRows/d.size),d.filteredPages=Math.ceil(d.filteredRows/d.size),s(b,d)},u=function(a,b){b.page=0,s(a,b)},v=function(a,b){b.page=Math.min(b.totalPages,b.filteredPages)-1,s(a,b)},w=function(a,b){b.page++,b.page>=Math.min(b.totalPages,b.filteredPages)-1&&(b.page=Math.min(b.totalPages,b.filteredPages)-1),s(a,b)},x=function(a,b){b.page--,b.page<=0&&(b.page=0),s(a,b)},y=function(d,e){q(d,e),e.$container.hide(),d.config.appender=null,e.initialized=!1,delete d.config.rowsCopy,a(d).unbind(c.split(" ").join(".pager ").replace(/\s+/g," ")),b.storage&&b.storage(d,e.storageKey,"")},z=function(c,d,e){var f,g=c.config;d.$size.add(d.$goto).add(d.$container.find(".ts-startRow, .ts-page")).removeClass(d.cssDisabled).removeAttr("disabled").attr("aria-disabled","false"),d.isDisabled=!1,d.page=a.data(c,"pagerLastPage")||d.page||0,d.size=a.data(c,"pagerLastSize")||parseInt(d.$size.find("option[selected]").val(),10)||d.size||d.settings.size||10,d.$size.val(d.size),d.totalPages=Math.ceil(Math.min(d.totalRows,d.filteredRows)/d.size),c.id&&(f=c.id+"_pager_info",d.$container.find(d.cssPageDisplay).attr("id",f),g.$table.attr("aria-describedby",f)),j(c,d),e&&(g.$table.trigger("updateRows"),t(c,d.size,d),l(c,d),g.debug&&b.log("Pager: Enabled"))};d.appender=function(b,c){var d=b.config,e=d.pager;e.ajax||(d.rowsCopy=c,e.totalRows=e.countChildRows?d.$tbodies.eq(0).children("tr").length:c.length,e.size=a.data(b,"pagerLastSize")||e.size||e.settings.size||10,e.totalPages=Math.ceil(e.totalRows/e.size),p(b,c,e),g(b,e,!1))},d.construct=function(e){return this.each(function(){if(this.config&&this.hasInitialized){var f,h,i,m=this,n=m.config,o=n.widgetOptions,p=n.pager=a.extend(!0,{},a.tablesorterPager.defaults,e),A=n.$table,B=p.$container=a(p.container).addClass("tablesorter-pager").show();p.settings=a.extend(!0,{},a.tablesorterPager.defaults,e),n.debug&&b.log("Pager: Initializing"),p.oldAjaxSuccess=p.oldAjaxSuccess||p.ajaxObject.success,n.appender=d.appender,p.initializing=!0,p.savePages&&b.storage&&(f=b.storage(m,p.storageKey)||{},p.page=isNaN(f.page)?p.page:f.page,p.size=(isNaN(f.size)?p.size:f.size)||p.settings.size||10,a.data(m,"pagerLastSize",p.size)),p.regexRows=new RegExp("("+(o.filter_filteredRow||"filtered")+"|"+n.selectorRemove.slice(1)+"|"+n.cssChildRow+")"),A.unbind(c.split(" ").join(".pager ").replace(/\s+/g," ")).bind("filterInit.pager filterStart.pager",function(b,c){p.currentFilters=a.isArray(c)?c:n.$table.data("lastSearch"),"filterStart"===b.type&&p.pageReset!==!1&&(n.lastCombinedFilter||"")!==(p.currentFilters||[]).join("")&&(p.page=p.pageReset)}).bind("filterEnd.pager sortEnd.pager",function(){p.currentFilters=n.$table.data("lastSearch"),(p.initialized||p.initializing)&&(n.delayInit&&n.rowsCopy&&0===n.rowsCopy.length&&r(m),g(m,p,!1),s(m,p,!1),n.$table.trigger("applyWidgets"))}).bind("disable.pager",function(a){a.stopPropagation(),q(m,p)}).bind("enable.pager",function(a){a.stopPropagation(),z(m,p,!0)}).bind("destroy.pager",function(a){a.stopPropagation(),y(m,p)}).bind("updateComplete.pager",function(a,b,c){if(a.stopPropagation(),b&&!c&&!p.ajax){var d=n.$tbodies.eq(0).children("tr").not(n.selectorRemove);p.totalRows=d.length-(p.countChildRows?0:d.filter("."+n.cssChildRow).length),p.totalPages=Math.ceil(p.totalRows/p.size),d.length&&n.rowsCopy&&0===n.rowsCopy.length&&r(b),p.page>=p.totalPages&&v(b,p),k(b,p),j(b,p),g(b,p,!0)}}).bind("pageSize.pager refreshComplete.pager",function(a,b){a.stopPropagation(),t(m,parseInt(b,10)||p.settings.size||10,p),k(m,p),g(m,p,!1)}).bind("pageSet.pager pagerUpdate.pager",function(a,b){a.stopPropagation(),"pagerUpdate"===a.type&&(b="undefined"==typeof b?p.page+1:b,p.last.page=!0),p.page=(parseInt(b,10)||1)-1,s(m,p,!0),g(m,p,!1)}).bind("pageAndSize.pager",function(a,b,c){a.stopPropagation(),p.page=(parseInt(b,10)||1)-1,t(m,parseInt(c,10)||p.settings.size||10,p),s(m,p,!0),k(m,p),g(m,p,!1)}),h=[p.cssFirst,p.cssPrev,p.cssNext,p.cssLast],i=[u,x,w,v],n.debug&&!B.length&&b.log("Pager: >> Container not found"),B.find(h.join(",")).attr("tabindex",0).unbind("click.pager").bind("click.pager",function(b){b.stopPropagation();var c,d=a(this),e=h.length;if(!d.hasClass(p.cssDisabled))for(c=0;e>c;c++)if(d.is(h[c])){i[c](m,p);break}}),p.$goto=B.find(p.cssGoto),p.$goto.length?p.$goto.unbind("change.pager").bind("change.pager",function(){p.page=a(this).val()-1,s(m,p,!0),g(m,p,!1)}):n.debug&&b.log("Pager: >> Goto selector not found"),p.$size=B.find(p.cssPageSize),p.$size.length?(p.$size.find("option").removeAttr("selected"),p.$size.unbind("change.pager").bind("change.pager",function(){return p.$size.val(a(this).val()),a(this).hasClass(p.cssDisabled)||(t(m,parseInt(a(this).val(),10),p),j(m,p)),!1})):n.debug&&b.log("Pager: >> Size selector not found"),p.initialized=!1,A.trigger("pagerBeforeInitialized",p),z(m,p,!1),"string"==typeof p.ajaxUrl?(p.ajax=!0,n.widgetOptions.filter_serversideFiltering=!0,n.serverSideSorting=!0,s(m,p)):(p.ajax=!1,a(this).trigger("appendCache",!0),l(m,p)),p.ajax||p.initialized||(p.initializing=!1,p.initialized=!0,s(m,p),n.debug&&b.log("Pager: Triggering pagerInitialized"),n.$table.trigger("pagerInitialized",p),n.widgetOptions.filter_initialized&&b.hasWidget(m,"filter")||g(m,p,!1)),n.widgetInit.pager=!0}})}}}),b.showError=function(b,c){var d,e,f,g,h=a(b),i=h.length;for(d=0;i>d;d++)f=h[d].config,f&&(g=f.pager&&f.pager.cssErrorRow||f.widgetOptions.pager_css&&f.widgetOptions.pager_css.errorRow||"tablesorter-errorRow","undefined"==typeof c?f.$table.find("thead").find(f.selectorRemove).remove():e=a(/tr\>/.test(c)?c:''+c+"").click(function(){a(this).remove()}).appendTo(f.$table.find("thead:first")).addClass(g+" "+f.selectorRemove.slice(1)).attr({role:"alert","aria-live":"assertive"}))},a.fn.extend({tablesorterPager:a.tablesorterPager.construct})}(jQuery); \ No newline at end of file Index: lams_central/web/includes/javascript/jquery.tablesorter-widgets.js =================================================================== diff -u -ra1b4a3143714e2704412c585131a93fee2d8c40b -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/web/includes/javascript/jquery.tablesorter-widgets.js (.../jquery.tablesorter-widgets.js) (revision a1b4a3143714e2704412c585131a93fee2d8c40b) +++ lams_central/web/includes/javascript/jquery.tablesorter-widgets.js (.../jquery.tablesorter-widgets.js) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -1,17 +1,3 @@ -/*! tableSorter (FORK) 2.16+ widgets - updated 12/22/2014 (v2.18.4) */ -;(function(k,A){ -var e=k.tablesorter=k.tablesorter||{}; -e.themes={bootstrap:{table:"table table-bordered table-striped",caption:"caption",header:"bootstrap-header",footerRow:"",footerCells:"",icons:"",sortNone:"bootstrap-icon-unsorted",sortAsc:"icon-chevron-up glyphicon glyphicon-chevron-up",sortDesc:"icon-chevron-down glyphicon glyphicon-chevron-down",active:"",hover:"",filterRow:"",even:"",odd:""},jui:{table:"ui-widget ui-widget-content ui-corner-all",caption:"ui-widget-content",header:"ui-widget-header ui-corner-all ui-state-default", footerRow:"",footerCells:"",icons:"ui-icon",sortNone:"ui-icon-carat-2-n-s",sortAsc:"ui-icon-carat-1-n",sortDesc:"ui-icon-carat-1-s",active:"ui-state-active",hover:"ui-state-hover",filterRow:"",even:"ui-widget-content",odd:"ui-state-default"}};k.extend(e.css,{filterRow:"tablesorter-filter-row",filter:"tablesorter-filter",wrapper:"tablesorter-wrapper",resizer:"tablesorter-resizer",sticky:"tablesorter-stickyHeader",stickyVis:"tablesorter-sticky-visible",stickyWrap:"tablesorter-sticky-wrapper"}); -e.storage= function(c,a,b,d){c=k(c)[0];var e,h,g=!1;e={};h=c.config;var m=k(c);c=d&&d.id||m.attr(d&&d.group||"data-table-group")||c.id||k(".tablesorter").index(m);d=d&&d.url||m.attr(d&&d.page||"data-table-page")||h&&h.fixedUrl||A.location.pathname;if("localStorage"in A)try{A.localStorage.setItem("_tmptest","temp"),g=!0,A.localStorage.removeItem("_tmptest")}catch(n){}k.parseJSON&&(g?e=k.parseJSON(localStorage[a]||"{}"):(h=document.cookie.split(/[;\s|=]/),e=k.inArray(a,h)+1,e=0!==e?k.parseJSON(h[e]||"{}"):{})); if((b||""===b)&&A.JSON&&JSON.hasOwnProperty("stringify"))e[d]||(e[d]={}),e[d][c]=b,g?localStorage[a]=JSON.stringify(e):(b=new Date,b.setTime(b.getTime()+31536E6),document.cookie=a+"="+JSON.stringify(e).replace(/\"/g,'"')+"; expires="+b.toGMTString()+"; path=/");else return e&&e[d]?e[d][c]:""}; -e.addHeaderResizeEvent=function(c,a,b){c=k(c)[0];var d;b=k.extend({},{timer:250},b);var e=c.config,h=e.widgetOptions,g=function(a){h.resize_flag=!0;d=[];e.$headers.each(function(){var a=k(this),b=a.data("savedSizes")|| [0,0],c=this.offsetWidth,e=this.offsetHeight;if(c!==b[0]||e!==b[1])a.data("savedSizes",[c,e]),d.push(this)});d.length&&!1!==a&&e.$table.trigger("resize",[d]);h.resize_flag=!1};g(!1);clearInterval(h.resize_timer);if(a)return h.resize_flag=!1;h.resize_timer=setInterval(function(){h.resize_flag||g()},b.timer)}; -e.addWidget({id:"uitheme",priority:10,format:function(c,a,b){var d,f,h,g=e.themes;d=a.$table;var m=a.$headers,n=a.theme||"jui",p=g[n]||g.jui,g=[p.sortNone,p.sortDesc,p.sortAsc,p.active].join(" "); a.debug&&(f=new Date);d.hasClass("tablesorter-"+n)&&a.theme===a.appliedTheme&&c.hasInitialized||(h=(c=p[a.appliedTheme]||{},[c.sortNone,c.sortDesc,c.sortAsc,c.active].join(" ")),c&&(b.zebra[0]=b.zebra[0].replace(" "+c.even,""),b.zebra[1]=b.zebra[1].replace(" "+c.odd,"")),""!==p.even&&(b.zebra[0]+=" "+p.even),""!==p.odd&&(b.zebra[1]+=" "+p.odd),d.children("caption").removeClass(c.caption).addClass(p.caption),b=d.removeClass(a.appliedTheme?"tablesorter-"+(a.appliedTheme||""):"").addClass("tablesorter-"+ n+" "+p.table).children("tfoot"),b.length&&b.children("tr").removeClass(c.footerRow||"").addClass(p.footerRow).children("th, td").removeClass(c.footerCells||"").addClass(p.footerCells),m.add(a.$extraHeaders).removeClass(c.header+" "+c.hover+" "+h).addClass(p.header).not(".sorter-false").bind("mouseenter.tsuitheme mouseleave.tsuitheme",function(a){k(this)["mouseenter"===a.type?"addClass":"removeClass"](p.hover)}),m.find("."+e.css.wrapper).length||m.wrapInner('
'), a.cssIcon&&m.find("."+e.css.icon).removeClass(c.icons+" "+h).addClass(p.icons),d.hasClass("hasFilters")&&d.children("thead").children("."+e.css.filterRow).removeClass(c.filterRow).addClass(p.filterRow),a.appliedTheme=a.theme);for(d=0;d=]/g,query:"(q|query)"},types:{regex:function(c,a){if(e.filter.regex.regex.test(a.iFilter)){var b,d=e.filter.regex.regex.exec(a.iFilter);try{b=(new RegExp(d[1],d[2])).test(a.iExact)}catch(f){b=!1}return b}return null},operators:function(c,a){if(/^[<>]=?/.test(a.iFilter)){var b,d;b=c.table;var f=a.index,h=a.parsed[f],g=e.formatFloat(a.iFilter.replace(e.filter.regex.operators,""),b),m= c.parsers[f],n=g;if(h||"numeric"===m.type)d=e.filter.parseFilter(c,k.trim(""+a.iFilter.replace(e.filter.regex.operators,"")),f,h,!0),g="number"!==typeof d||""===d||isNaN(d)?g:d;b=!h&&"numeric"!==m.type||isNaN(g)||"undefined"===typeof a.cache?isNaN(a.iExact)?e.formatFloat(a.iExact.replace(e.filter.regex.nondigit,""),b):e.formatFloat(a.iExact,b):a.cache;/>/.test(a.iFilter)&&(d=/>=/.test(a.iFilter)?b>=g:b>g);/n&&(d=k,k=n,n=d);return b>=k&&b<=n||""===k||""===n}return null},wild:function(c,a){if(/[\?\*\|]/.test(a.iFilter)||e.filter.regex.orReplace.test(a.filter)){var b=a.index,d=a.parsed[b],d=e.filter.parseFilter(c,a.iFilter.replace(e.filter.regex.orReplace,"|"),b,d);!c.$headers.filter('[data-column="'+b+'"]:last').hasClass("filter-match")&&/\|/.test(d)&&("|"===d[d.length-1]&&(d+="*"),d=a.anyMatch&&k.isArray(a.rowArray)?"("+d+")":"^("+d+")$");return(new RegExp(d.replace(/\?/g,"\\S{1}").replace(/\*/g, "\\S*"))).test(a.iExact)}return null},fuzzy:function(c,a){if(/^~/.test(a.iFilter)){var b,d=0,f=a.iExact.length,h=e.filter.parseFilter(c,a.iFilter.slice(1),a.index,a.parsed[a.index]);for(b=0;b'+(g.data("placeholder")||g.attr("data-placeholder")||b.filter_placeholder.select||"")+"":"",h=p=f,0<=f.indexOf(b.filter_selectSourceSeparator)&&(p=f.split(b.filter_selectSourceSeparator),h=p[1],p=p[0]),d+="");a.$table.find("thead").find("select."+ e.css.filter+'[data-column="'+m+'"]').append(d)}e.filter.buildDefault(c,!0);e.filter.bindSearch(c,a.$table.find("."+e.css.filter),!0);b.filter_external&&e.filter.bindSearch(c,b.filter_external);b.filter_hideFilters&&e.filter.hideFilters(c,a);a.showProcessing&&a.$table.bind("filterStart"+a.namespace+"filter filterEnd"+a.namespace+"filter",function(b,d){g=d?a.$table.find("."+e.css.header).filter("[data-column]").filter(function(){return""!==d[k(this).data("column")]}):"";e.isProcessing(c,"filterStart"=== b.type,d?g:"")});a.filteredRows=a.totalRows;a.$table.bind("tablesorter-initialized pagerBeforeInitialized",function(){var b=this.config.widgetOptions;n=e.filter.setDefaults(c,a,b)||[];n.length&&(a.delayInit&&""===n.join("")||e.setFilters(c,n,!0));a.$table.trigger("filterFomatterUpdate");setTimeout(function(){b.filter_initialized||e.filter.filterInitComplete(a)},100)});a.pager&&a.pager.initialized&&!b.filter_initialized&&(a.$table.trigger("filterFomatterUpdate"),setTimeout(function(){e.filter.filterInitComplete(a)}, 100))},formatterUpdated:function(c,a){var b=c.closest("table")[0].config.widgetOptions;b.filter_initialized||(b.filter_formatterInit[a]=1)},filterInitComplete:function(c){var a=c.widgetOptions,b=0,d=function(){a.filter_initialized=!0;c.$table.trigger("filterInit",c);e.filter.findRows(c.table,c.$table.data("lastSearch")||[])};k.isEmptyObject(a.filter_formatter)?d():(k.each(a.filter_formatterInit,function(a,c){1===c&&b++}),clearTimeout(a.filter_initTimer),a.filter_initialized||b!==a.filter_formatterCount)? a.filter_initialized||(a.filter_initTimer=setTimeout(function(){d()},500)):d()},setDefaults:function(c,a,b){var d,f=e.getFilters(c)||[];b.filter_saveFilters&&e.storage&&(d=e.storage(c,"tablesorter-filters")||[],(c=k.isArray(d))&&""===d.join("")||!c||(f=d));if(""===f.join(""))for(c=0;c';for(f=0;f"):g+("");a.$filters=k(g+"").appendTo(a.$table.children("thead").eq(0)).find("td");for(f=0;f").appendTo(a.$filters.eq(f)):((g=e.getColumnData(c,b.filter_formatter,f))?(b.filter_formatterCount++,(g=g(a.$filters.eq(f),f))&&0===g.length&&(g=a.$filters.eq(f).children("input")),g&&(0===g.parent().length||g.parent().length&&g.parent()[0]!==a.$filters[f])&&a.$filters.eq(f).append(g)):g=k('').appendTo(a.$filters.eq(f)), g&&g.attr("placeholder",h.data("placeholder")||h.attr("data-placeholder")||b.filter_placeholder.search||"")),g&&(h=(k.isArray(b.filter_cssFilter)?"undefined"!==typeof b.filter_cssFilter[f]?b.filter_cssFilter[f]||"":"":b.filter_cssFilter)||"",g.addClass(e.css.filter+" "+h).attr("data-column",f),d&&(g.attr("placeholder","").addClass("disabled")[0].disabled=!0))},bindSearch:function(c,a,b){c=k(c)[0];a=k(a);if(a.length){var d=c.config,f=d.widgetOptions,h=f.filter_$externalFilters;!0!==b&&(f.filter_$anyMatch= a.filter(f.filter_anyColumnSelector+","+f.filter_multipleColumnSelector),f.filter_$externalFilters=h&&h.length?f.filter_$externalFilters.add(a):a,e.setFilters(c,d.$table.data("lastSearch")||[],!1===b));a.attr("data-lastSearchTime",(new Date).getTime()).unbind(["keypress","keyup","search","change",""].join(d.namespace+"filter ")).bind("keyup"+d.namespace+"filter",function(a){k(this).attr("data-lastSearchTime",(new Date).getTime());if(27===a.which)this.value="";else if(!1===f.filter_liveSearch||""!== this.value&&("number"===typeof f.filter_liveSearch&&this.value.lengtha.which||37<=a.which&&40>=a.which)))return;e.filter.searching(c,!0,!0)}).bind(["search","change","keypress",""].join(d.namespace+"filter "),function(a){var b=k(this).data("column");if(13===a.which||"search"===a.type||"change"===a.type&&this.value!==d.lastSearch[b])a.preventDefault(),k(this).attr("data-lastSearchTime",(new Date).getTime()),e.filter.searching(c,!1,!0)})}},searching:function(c, a,b){var d=c.config.widgetOptions;clearTimeout(d.searchTimer);"undefined"===typeof a||!0===a?d.searchTimer=setTimeout(function(){e.filter.checkFilters(c,a,b)},d.filter_liveSearch?d.filter_searchDelay:10):e.filter.checkFilters(c,a,b)},checkFilters:function(c,a,b){var d=c.config,f=d.widgetOptions,h=k.isArray(a),g=h?a:e.getFilters(c,!0),m=(g||[]).join("");if(k.isEmptyObject(d.cache))d.delayInit&&d.pager&&d.pager.initialized&&d.$table.trigger("updateCache",[function(){e.filter.checkFilters(c,!1,b)}]); else if(h&&(e.setFilters(c,g,!1,!0!==b),f.filter_initialized||(d.lastCombinedFilter="")),f.filter_hideFilters&&d.$table.find("."+e.css.filterRow).trigger(""===m?"mouseleave":"mouseenter"),d.lastCombinedFilter!==m||!1===a)if(!1===a&&(d.lastCombinedFilter=null,d.lastSearch=[]),f.filter_initialized&&d.$table.trigger("filterStart",[g]),d.showProcessing)setTimeout(function(){e.filter.findRows(c,g,m);return!1},30);else return e.filter.findRows(c,g,m),!1},hideFilters:function(c,a){var b,d,f;k(c).find("."+ e.css.filterRow).addClass("hideme").bind("mouseenter mouseleave",function(c){b=k(this);clearTimeout(f);f=setTimeout(function(){/enter|over/.test(c.type)?b.removeClass("hideme"):k(document.activeElement).closest("tr")[0]!==b[0]&&""===a.lastCombinedFilter&&b.addClass("hideme")},200)}).find("input, select").bind("focus blur",function(b){d=k(this).closest("tr");clearTimeout(f);f=setTimeout(function(){if(""===e.getFilters(a.$table).join(""))d["focus"===b.type?"removeClass":"addClass"]("hideme")},200)})}, defaultFilter:function(c,a){if(""===c)return c;var b=e.filter.regex.iQuery,d=a.match(e.filter.regex.igQuery).length,f=1h&&1f&&(d=e,e=f,f=d);for(f>=c.columns&&(f=c.columns-1);e<=f;e++)h.push(e);g=g.replace(b,"")}));f&&/,/.test(g)&&(b=g.split(/\s*,\s*/),k.each(b,function(a,b){""!==b&&(d=parseInt(b,10),d=?\s*-\d)/.test(z)||/(<=?\s*\d)/.test(z))&&!(""!==z&&q.$filters&&q.$filters.eq(n).find("select").length&&!q.$headers.filter('[data-column="'+n+'"]:last').hasClass("filter-match"));z=f.not("."+v.filter_filteredRow).length;B&&0===z&&(B=!1);q.debug&&e.log("Searching through "+(B&&zk.inArray(a,J)&&(t=b(q,l),null!==t))return C=t,!1});if(null!==C)y=C;else if(v.filter_startsWith)for(y=!1,r=q.columns;!y&&0k.inArray(a,G)&&(t=b(q,l),null!==t))return C=t,!1}),null!==C?u=C:(l.exact=(l.iExact+l.childRowText).indexOf(e.filter.parseFilter(q,l.iFilter,r,l.parsed[r])),u=!v.filter_startsWith&&0<=l.exact||v.filter_startsWith&& 0===l.exact)),y=u?y:!1);f.eq(h).toggle(y).toggleClass(v.filter_filteredRow,!y);w.length&&w.toggleClass(v.filter_filteredRow,!y)}}q.filteredRows+=f.not("."+v.filter_filteredRow).length;q.totalRows+=f.length;e.processTbody(c,m,!1)}q.lastCombinedFilter=b;q.lastSearch=a;q.$table.data("lastSearch",a);v.filter_saveFilters&&e.storage&&e.storage(c,"tablesorter-filters",a);q.debug&&e.benchmark("Completed filter widget search",A);v.filter_initialized&&q.$table.trigger("filterEnd",q);setTimeout(function(){q.$table.trigger("applyWidgets")}, 0)}},getOptionSource:function(c,a,b){var d,f=c.config,h=[],g=!1,m=f.widgetOptions.filter_selectSource,n=f.$table.data("lastSearch")||[],p=k.isFunction(m)?!0:e.getColumnData(c,m,a);b&&""!==n[a]&&(b=!1);if(!0===p)g=m(c,a,b);else{if(p instanceof k||"string"===k.type(p)&&0<=p.indexOf(""))return p;k.isArray(p)?g=p:"object"===k.type(m)&&p&&(g=p(c,a,b))}!1===g&&(g=e.filter.getOptions(c,a,b));g=k.grep(g,function(a,b){return k.inArray(a,g)===b});f.$headers.filter('[data-column="'+a+'"]:last').hasClass("filter-select-nosort")|| (k.each(g,function(b,d){h.push({t:d,p:f.parsers&&f.parsers[a].format(d,c,[],a)})}),d=f.textSorter||"",h.sort(function(b,f){var g=b.p.toString(),h=f.p.toString();return k.isFunction(d)?d(g,h,!0,a,c):"object"===typeof d&&d.hasOwnProperty(a)?d[a](g,h,!0,a,c):e.sortNatural?e.sortNatural(g,h):!0}),g=[],k.each(h,function(a,b){g.push(b.t)}));return g},getOptions:function(c,a,b){var d,e,h,g,m=c.config,n=m.widgetOptions,p=m.$table.children("tbody"),r=[];for(d=0;d'+(n.data("placeholder")||n.attr("data-placeholder")||m.filter_placeholder.select||"")+"",p=g.$table.find("thead").find("select."+e.css.filter+'[data-column="'+a+'"]').val();if("undefined"===typeof b||""===b)b=e.filter.getOptionSource(c,a,f);if(k.isArray(b)){for(c=0;c'+h+"":"";b=[]}g=(g.$filters?g.$filters:g.$table.children("thead")).find("."+e.css.filter);m.filter_$externalFilters&&(g=g&&g.length?g.add(m.filter_$externalFilters):m.filter_$externalFilters);a=g.filter('select[data-column="'+a+'"]');a.length&&(a[d?"html":"append"](n),k.isArray(b)||a.append(b).val(p),a.val(p))}},buildDefault:function(c,a){var b,d,f,h=c.config,g=h.widgetOptions,k=h.columns;for(b= 0;b'),y=u.parent().css({position:f.length? "absolute":"fixed",padding:parseInt(u.parent().parent().css("padding-left"),10),top:w+t,left:0,visibility:"hidden",zIndex:b.stickyHeaders_zIndex||2}),E=u.children("thead:first"),z,B="",C=0,G=function(a,b){a.filter(":visible").each(function(a){var d;a=b.filter(":visible").eq(a);var c=k(this);"border-box"===c.css("box-sizing")?d=c.outerWidth():"collapse"===a.css("border-collapse")?A.getComputedStyle?d=parseFloat(A.getComputedStyle(this,null).width):(d=parseFloat(c.css("border-width")),d=c.outerWidth()- parseFloat(c.css("padding-left"))-parseFloat(c.css("padding-right"))-d):d=c.width();a.css({"min-width":d,"max-width":d})})},D=function(){w=r.length?r.height()||0:parseInt(b.stickyHeaders_offset,10)||0;C=0;y.css({left:f.length?parseInt(f.css("padding-left"),10)||0:d.offset().left-parseInt(d.css("margin-left"),10)-m.scrollLeft()-C,width:d.outerWidth()});G(d,u);G(n,z)};u.attr("id")&&(u[0].id+=b.stickyHeaders_cloneId);u.find("thead:gt(0), tr.sticky-false").hide();u.find("tbody, tfoot").remove();u.find("caption").toggle(b.stickyHeaders_includeCaption); z=E.children().children();u.css({height:0,width:0,margin:0});z.find("."+e.css.resizer).remove();d.addClass("hasStickyHeaders").bind("pagerComplete"+h,function(){D()});e.bindEvents(c,E.children().children(".tablesorter-header"));d.after(y);a.onRenderHeader&&E.children("tr").children().each(function(b){a.onRenderHeader.apply(k(this),[b,a,u])});m.add(g).unbind(["scroll","resize",""].join(h)).bind(["scroll","resize",""].join(h),function(a){if(d.is(":visible")){t=x.length?x.offset().top-g.scrollTop()+ x.height():0;var b=d.offset(),c=k.isWindow(g[0]),e=k.isWindow(m[0]),h=(f.length?c?g.scrollTop():g.offset().top:g.scrollTop())+w+t,l=d.height()-(y.height()+(p.height()||0)),b=h>b.top&&hMath.abs(p.parent().width()-p.width()),E=function(a){if(0!==x&&t){var b=a.pageX-x,c=t.width();t.width(c+b);t.width()!==c&&y?u.width(u.width()-b):w&&(p.width(function(a,c){return c+b}),u.length|| (r[0].scrollLeft=p.width()));x=a.pageX}},z=function(){e.storage&&t&&u&&(n={},n[t.index()]=t.width(),n[u.index()]=u.width(),t.width(n[t.index()]),u.width(n[u.index()]),!1!==b.resizable&&e.storage(c,"tablesorter-resizable",a.$headers.map(function(){return k(this).width()}).get()));x=0;t=u=null;k(A).trigger("resize")};if(n=e.storage&&!1!==b.resizable?e.storage(c,"tablesorter-resizable"):{})for(g in n)!isNaN(g)&&g');b.resizable_addLastColumn||(h=h.slice(0,-1));f=f?f.add(h):h});f.each(function(){var a= k(this),b=parseInt(a.css("padding-right"),10)+10;a.find("."+e.css.wrapper).append('
')}).find("."+e.css.resizer).bind("mousedown",function(b){t=k(b.target).closest("th");var c=a.$headers.filter('[data-column="'+t.attr("data-column")+'"]');1')}),d.cssIcon&&t.find("."+b.css.icon).removeClass(q?[n.icons,p].join(" "):"").addClass(v.icons||""),s.hasClass("hasFilters")&&s.children("thead").children("."+b.css.filterRow).removeClass(q?n.filterRow||"":"").addClass(v.filterRow||"")),f=0;f1)))for(m=1;q>m;m++)k.eq(p[m][0]).addClass(r[m]||r[s])}),b.processTbody(c,f,!1);if(i=e.columns_thead!==!1?["thead tr"]:[],e.columns_tfoot!==!1&&i.push("tfoot tr"),i.length&&(h=n.find(i.join(",")).children().removeClass(l),q))for(m=0;q>m;m++)h.filter('[data-column="'+p[m][0]+'"]').addClass(r[m]||r[s])},remove:function(c,d,e){var f,g,h=d.$tbodies,i=(e.columns||["primary","secondary","tertiary"]).join(" ");for(d.$headers.removeClass(i),d.$table.children("tfoot").children("tr").children("th, td").removeClass(i),f=0;f=]/g,query:"(q|query)"},types:{regex:function(a,c){if(b.filter.regex.regex.test(c.filter)){var d,e=c.filter_regexCache[c.index]||b.filter.regex.regex.exec(c.filter),f=e instanceof RegExp;try{f||(c.filter_regexCache[c.index]=e=new RegExp(e[1],e[2])),d=e.test(c.exact)}catch(g){d=!1}return d}return null},operators:function(c,d){if(/^[<>]=?/.test(d.iFilter)&&""!==d.iExact){var e,f,g,h=c.table,i=d.index,j=d.parsed[i],k=b.formatFloat(d.iFilter.replace(b.filter.regex.operators,""),h),l=c.parsers[i],m=k;return(j||"numeric"===l.type)&&(g=a.trim(""+d.iFilter.replace(b.filter.regex.operators,"")),f=b.filter.parseFilter(c,g,i,!0),k="number"!=typeof f||""===f||isNaN(f)?k:f),!j&&"numeric"!==l.type||isNaN(k)||"undefined"==typeof d.cache?(g=isNaN(d.iExact)?d.iExact.replace(b.filter.regex.nondigit,""):d.iExact,e=b.formatFloat(g,h)):e=d.cache,/>/.test(d.iFilter)?f=/>=/.test(d.iFilter)?e>=k:e>k:/=e:k>e),f||""!==m||(f=!0),f}return null},notMatch:function(c,d){if(/^\!/.test(d.iFilter)){var e,f=d.iFilter.replace("!",""),g=b.filter.parseFilter(c,f,d.index,d.parsed[d.index])||"";return b.filter.regex.exact.test(g)?(g=g.replace(b.filter.regex.exact,""),""===g?!0:a.trim(g)!==d.iExact):(e=d.iExact.search(a.trim(g)),""===g?!0:!(c.widgetOptions.filter_startsWith?0===e:e>=0))}return null},exact:function(c,d){if(b.filter.regex.exact.test(d.iFilter)){var e=d.iFilter.replace(b.filter.regex.exact,""),f=b.filter.parseFilter(c,e,d.index,d.parsed[d.index])||"";return d.anyMatch?a.inArray(f,d.rowArray)>=0:f==d.iExact}return null},and:function(c,d){if(b.filter.regex.andTest.test(d.filter)){for(var e=d.index,f=d.parsed[e],g=d.iFilter.split(b.filter.regex.andSplit),h=d.iExact.search(a.trim(b.filter.parseFilter(c,g[0],e,f)))>=0,i=g.length-1;h&&i;)h=h&&d.iExact.search(a.trim(b.filter.parseFilter(c,g[i],e,f)))>=0,i--;return h}return null},range:function(a,c){if(b.filter.regex.toTest.test(c.iFilter)){var d,e,f,g,h=a.table,i=c.index,j=c.parsed[i],k=c.iFilter.split(b.filter.regex.toSplit);return e=k[0].replace(b.filter.regex.nondigit,"")||"",f=b.formatFloat(b.filter.parseFilter(a,e,i,j),h),e=k[1].replace(b.filter.regex.nondigit,"")||"",g=b.formatFloat(b.filter.parseFilter(a,e,i,j),h),(j||"numeric"===a.parsers[i].type)&&(d=a.parsers[i].format(""+k[0],h,a.$headers.eq(i),i),f=""===d||isNaN(d)?f:d,d=a.parsers[i].format(""+k[1],h,a.$headers.eq(i),i),g=""===d||isNaN(d)?g:d),!j&&"numeric"!==a.parsers[i].type||isNaN(f)||isNaN(g)?(e=isNaN(c.iExact)?c.iExact.replace(b.filter.regex.nondigit,""):c.iExact,d=b.formatFloat(e,h)):d=c.cache,f>g&&(e=f,f=g,g=e),d>=f&&g>=d||""===f||""===g}return null},wild:function(c,d){if(/[\?\*\|]/.test(d.iFilter)||b.filter.regex.orReplace.test(d.filter)){var e=d.index,f=d.parsed[e],g=d.iFilter.replace(b.filter.regex.orReplace,"|"),h=""+(b.filter.parseFilter(c,g,e,f)||"");return!c.$headerIndexed[e].hasClass("filter-match")&&/\|/.test(h)&&("|"===h[h.length-1]&&(h+="*"),h=d.anyMatch&&a.isArray(d.rowArray)?"("+h+")":"^("+h+")$"),new RegExp(h.replace(/\?/g,"\\S{1}").replace(/\*/g,"\\S*")).test(d.iExact)}return null},fuzzy:function(a,c){if(/^~/.test(c.iFilter)){var d,e=0,f=c.iExact.length,g=c.iFilter.slice(1),h=b.filter.parseFilter(a,g,c.index,c.parsed[c.index])||"";for(d=0;f>d;d++)c.iExact[d]===h[e]&&(e+=1);return e===h.length?!0:!1}return null}},init:function(d,e,f){b.language=a.extend(!0,{},{to:"to",or:"or",and:"and"},b.language);var g,h,i,j,k,l,m,n,o,p=b.filter.regex;if(e.$table.addClass("hasFilters"),f.searchTimer=null,f.filter_initTimer=null,f.filter_formatterCount=0,f.filter_formatterInit=[],f.filter_anyColumnSelector='[data-column="all"],[data-column="any"]',f.filter_multipleColumnSelector='[data-column*="-"],[data-column*=","]',m="\\{"+b.filter.regex.query+"\\}",a.extend(p,{child:new RegExp(e.cssChildRow),filtered:new RegExp(f.filter_filteredRow),alreadyFiltered:new RegExp("(\\s+("+b.language.or+"|-|"+b.language.to+")\\s+)","i"),toTest:new RegExp("\\s+(-|"+b.language.to+")\\s+","i"),toSplit:new RegExp("(?:\\s+(?:-|"+b.language.to+")\\s+)","gi"),andTest:new RegExp("\\s+("+b.language.and+"|&&)\\s+","i"),andSplit:new RegExp("(?:\\s+(?:"+b.language.and+"|&&)\\s+)","gi"),orReplace:new RegExp("\\s+("+b.language.or+")\\s+","gi"),iQuery:new RegExp(m,"i"),igQuery:new RegExp(m,"ig")}),m=e.$headers.filter(".filter-false, .parser-false").length,f.filter_columnFilters!==!1&&m!==e.$headers.length&&b.filter.buildRow(d,e,f),i="addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search ".split(" ").join(e.namespace+"filter "),e.$table.bind(i,function(g,h){return m=f.filter_hideEmpty&&a.isEmptyObject(e.cache)&&!(e.delayInit&&"appendCache"===g.type),e.$table.find("."+c.filterRow).toggleClass(f.filter_filteredRow,m),/(search|filter)/.test(g.type)||(g.stopPropagation(),b.filter.buildDefault(d,!0)),"filterReset"===g.type?(e.$table.find("."+c.filter).add(f.filter_$externalFilters).val(""),b.filter.searching(d,[])):"filterEnd"===g.type?b.filter.buildDefault(d,!0):(h="search"===g.type?h:"updateComplete"===g.type?e.$table.data("lastSearch"):"",/(update|add)/.test(g.type)&&"updateComplete"!==g.type&&(e.lastCombinedFilter=null,e.lastSearch=[]),b.filter.searching(d,h,!0)),!1}),f.filter_reset&&(f.filter_reset instanceof a?f.filter_reset.click(function(){e.$table.trigger("filterReset")}):a(f.filter_reset).length&&a(document).undelegate(f.filter_reset,"click.tsfilter").delegate(f.filter_reset,"click.tsfilter",function(){e.$table.trigger("filterReset")})),f.filter_functions)for(k=0;k'+(j.data("placeholder")||j.attr("data-placeholder")||f.filter_placeholder.select||"")+"":"",m=h,i=h,h.indexOf(f.filter_selectSourceSeparator)>=0&&(m=h.split(f.filter_selectSourceSeparator),i=m[1],m=m[0]),g+="");e.$table.find("thead").find("select."+c.filter+'[data-column="'+k+'"]').append(g),i=f.filter_selectSource,n=a.isFunction(i)?!0:b.getColumnData(d,i,k),n&&b.filter.buildSelect(e.table,k,"",!0,j.hasClass(f.filter_onlyAvail))}b.filter.buildDefault(d,!0),b.filter.bindSearch(d,e.$table.find("."+c.filter),!0),f.filter_external&&b.filter.bindSearch(d,f.filter_external),f.filter_hideFilters&&b.filter.hideFilters(d,e),e.showProcessing&&(i="filterStart filterEnd ".split(" ").join(e.namespace+"filter "),e.$table.unbind(i.replace(/\s+/g," ")).bind(i,function(f,g){j=g?e.$table.find("."+c.header).filter("[data-column]").filter(function(){return""!==g[a(this).data("column")]}):"",b.isProcessing(d,"filterStart"===f.type,g?j:"")})),e.filteredRows=e.totalRows,i="tablesorter-initialized pagerBeforeInitialized ".split(" ").join(e.namespace+"filter "),e.$table.unbind(i.replace(/\s+/g," ")).bind(i,function(){var a=this.config.widgetOptions;l=b.filter.setDefaults(d,e,a)||[],l.length&&(e.delayInit&&""===l.join("")||b.setFilters(d,l,!0)),e.$table.trigger("filterFomatterUpdate"),setTimeout(function(){a.filter_initialized||b.filter.filterInitComplete(e)},100)}),e.pager&&e.pager.initialized&&!f.filter_initialized&&(e.$table.trigger("filterFomatterUpdate"),setTimeout(function(){b.filter.filterInitComplete(e)},100))},formatterUpdated:function(a,b){var c=a.closest("table")[0].config.widgetOptions;c.filter_initialized||(c.filter_formatterInit[b]=1)},filterInitComplete:function(c){var d,e,f=c.widgetOptions,g=0,h=function(){f.filter_initialized=!0,c.$table.trigger("filterInit",c),b.filter.findRows(c.table,c.$table.data("lastSearch")||[])};if(a.isEmptyObject(f.filter_formatter))h();else{for(e=f.filter_formatterInit.length,d=0;e>d;d++)1===f.filter_formatterInit[d]&&g++;clearTimeout(f.filter_initTimer),f.filter_initialized||g!==f.filter_formatterCount?f.filter_initialized||(f.filter_initTimer=setTimeout(function(){h()},500)):h()}},setDefaults:function(c,d,e){var f,g,h,i,j,k=b.getFilters(c)||[];if(e.filter_saveFilters&&b.storage&&(g=b.storage(c,"tablesorter-filters")||[],f=a.isArray(g),f&&""===g.join("")||!f||(k=g)),""===k.join(""))for(j=d.$headers.add(e.filter_$externalFilters).filter("["+e.filter_defaultAttrib+"]"),h=0;h<=d.columns;h++)i=h===d.columns?"all":h,k[h]=j.filter('[data-column="'+i+'"]').attr(e.filter_defaultAttrib)||k[h]||"";return d.$table.data("lastSearch",k),k},parseFilter:function(a,b,c,d){return d?a.parsers[c].format(b,a.table,[],c):b},buildRow:function(d,e,f){var g,h,i,j,k,l,m,n,o=f.filter_cellFilter,p=e.columns,q=a.isArray(o),r='';for(h=0;p>h;h++)r+="").appendTo(e.$table.children("thead").eq(0)).find("td"),h=0;p>h;h++)k=!1,i=e.$headerIndexed[h],m=b.getColumnData(d,f.filter_functions,h),j=f.filter_functions&&m&&"function"!=typeof m||i.hasClass("filter-select"),g=b.getColumnData(d,e.headers,h),k="false"===b.getData(i[0],g,"filter")||"false"===b.getData(i[0],g,"parser"),j?r=a("').appendTo(e.$filters.eq(h)),r&&(n=i.data("placeholder")||i.attr("data-placeholder")||f.filter_placeholder.search||"",r.attr("placeholder",n))),r&&(l=(a.isArray(f.filter_cssFilter)?"undefined"!=typeof f.filter_cssFilter[h]?f.filter_cssFilter[h]||"":"":f.filter_cssFilter)||"",r.addClass(c.filter+" "+l).attr("data-column",h),k&&(r.attr("placeholder","").addClass(c.filterDisabled)[0].disabled=!0))},bindSearch:function(c,d,e){if(c=a(c)[0],d=a(d),d.length){var f,g=c.config,h=g.widgetOptions,i=g.namespace+"filter",j=h.filter_$externalFilters;e!==!0&&(f=h.filter_anyColumnSelector+","+h.filter_multipleColumnSelector,h.filter_$anyMatch=d.filter(f),j&&j.length?h.filter_$externalFilters=h.filter_$externalFilters.add(d):h.filter_$externalFilters=d,b.setFilters(c,g.$table.data("lastSearch")||[],e===!1)),f="keypress keyup search change ".split(" ").join(i+" "),d.attr("data-lastSearchTime",(new Date).getTime()).unbind(f.replace(/\s+/g," ")).bind("keyup"+i,function(d){if(a(this).attr("data-lastSearchTime",(new Date).getTime()),27===d.which)this.value="";else{if(h.filter_liveSearch===!1)return;if(""!==this.value&&("number"==typeof h.filter_liveSearch&&this.value.length=37&&d.which<=40)))return}b.filter.searching(c,!0,!0)}).bind("search change keypress ".split(" ").join(i+" "),function(d){var e=a(this).data("column");(13===d.which||"search"===d.type||"change"===d.type&&this.value!==g.lastSearch[e])&&(d.preventDefault(),a(this).attr("data-lastSearchTime",(new Date).getTime()),b.filter.searching(c,!1,!0))})}},searching:function(a,c,d){var e=a.config.widgetOptions;clearTimeout(e.searchTimer),"undefined"==typeof c||c===!0?e.searchTimer=setTimeout(function(){b.filter.checkFilters(a,c,d)},e.filter_liveSearch?e.filter_searchDelay:10):b.filter.checkFilters(a,c,d)},checkFilters:function(d,e,f){var g=d.config,h=g.widgetOptions,i=a.isArray(e),j=i?e:b.getFilters(d,!0),k=(j||[]).join("");return a.isEmptyObject(g.cache)?void(g.delayInit&&g.pager&&g.pager.initialized&&g.$table.trigger("updateCache",[function(){b.filter.checkFilters(d,!1,f)}])):(i&&(b.setFilters(d,j,!1,f!==!0),h.filter_initialized||(g.lastCombinedFilter="")),h.filter_hideFilters&&g.$table.find("."+c.filterRow).trigger(""===k?"mouseleave":"mouseenter"),g.lastCombinedFilter!==k||e===!1?(e===!1&&(g.lastCombinedFilter=null,g.lastSearch=[]),h.filter_initialized&&g.$table.trigger("filterStart",[j]),g.showProcessing?void setTimeout(function(){return b.filter.findRows(d,j,k),!1},30):(b.filter.findRows(d,j,k),!1)):void 0)},hideFilters:function(d,e){var f,g,h;a(d).find("."+c.filterRow).addClass(c.filterRowHide).bind("mouseenter mouseleave",function(b){var d=b;f=a(this),clearTimeout(h),h=setTimeout(function(){/enter|over/.test(d.type)?f.removeClass(c.filterRowHide):a(document.activeElement).closest("tr")[0]!==f[0]&&""===e.lastCombinedFilter&&f.addClass(c.filterRowHide)},200)}).find("input, select").bind("focus blur",function(d){g=a(this).closest("tr"),clearTimeout(h);var f=d;h=setTimeout(function(){""===b.getFilters(e.$table).join("")&&g.toggleClass(c.filterRowHide,"focus"===f.type)},200)})},defaultFilter:function(c,d){if(""===c)return c;var e=b.filter.regex.iQuery,f=d.match(b.filter.regex.igQuery).length,g=f>1?a.trim(c).split(/\s/):[a.trim(c)],h=g.length-1,i=0,j=d;for(1>h&&f>1&&(g[1]=g[0]);e.test(j);)j=j.replace(e,g[i++]||""),e.test(j)&&h>i&&""!==(g[i]||"")&&(j=d.replace(e,j));return j},getLatestSearch:function(b){return b?b.sort(function(b,c){return a(c).attr("data-lastSearchTime")-a(b).attr("data-lastSearchTime")}):b||a()},multipleColumns:function(c,d){var e,f,g,h,i,j,k,l,m,n=c.widgetOptions,o=n.filter_initialized||!d.filter(n.filter_anyColumnSelector).length,p=[],q=a.trim(b.filter.getLatestSearch(d).attr("data-column")||"");if(o&&/-/.test(q))for(f=q.match(/(\d+)\s*-\s*(\d+)/g),m=f.length,l=0;m>l;l++){for(g=f[l].split(/\s*-\s*/),h=parseInt(g[0],10)||0,i=parseInt(g[1],10)||c.columns-1,h>i&&(e=h,h=i,i=e),i>=c.columns&&(i=c.columns-1);i>=h;h++)p.push(h);q=q.replace(f[l],"")}if(o&&/,/.test(q))for(j=q.split(/\s*,\s*/),m=j.length,k=0;m>k;k++)""!==j[k]&&(l=parseInt(j[k],10),l-1?(d.parsed[e]?p=d.cacheArray[e]:(p=d.rawArray[e],p=a.trim(r.filter_ignoreCase?p.toLowerCase():p),c.sortLocaleCompare&&(p=b.replaceAccents(p))),p):void 0}).get(),d.filter=d.anyMatchFilter,d.iFilter=d.iAnyMatchFilter,d.exact=d.rowArray.join(" "),d.iExact=r.filter_ignoreCase?d.exact.toLowerCase():d.exact,d.cache=d.cacheArray.slice(0,-1).join(" "),l=null,i=null;for(o in b.filter.types)a.inArray(o,e.noAnyMatch)<0&&null===i&&(i=b.filter.types[o](c,d),null!==i&&(l=i));if(null!==l)s=l;else if(r.filter_startsWith)for(s=!1,g=c.columns;!s&&g>0;)g--,s=s||0===d.rowArray[g].indexOf(d.iFilter);else s=(d.iExact+d.childRowText).indexOf(d.iFilter)>=0;if(d.anyMatch=!1,d.filters.join("")===d.filter)return s}for(g=0;g=0:d.filter===d.exact:"function"==typeof n?l=n(d.exact,d.cache,d.filter,g,d.$row,c,d):"function"==typeof n[o||d.filter]&&(p=o||d.filter,l=n[p](d.exact,d.cache,d.filter,g,d.$row,c,d))),null===l){i=null;for(o in b.filter.types)a.inArray(o,m)<0&&null===i&&(i=b.filter.types[o](c,d),null!==i&&(l=i));null!==l?j=l:(p=(d.iExact+d.childRowText).indexOf(b.filter.parseFilter(c,d.iFilter,g,d.parsed[g])),j=!r.filter_startsWith&&p>=0||r.filter_startsWith&&0===p)}else j=l;s=j?s:!1}return s},findRows:function(c,d,e){if(c.config.lastCombinedFilter!==e&&c.config.widgetOptions.filter_initialized){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=a.extend([],d),C=b.filter.regex,D=c.config,E=D.widgetOptions,F={anyMatch:!1,filters:d,filter_regexCache:[]},G={noAnyMatch:["range","notMatch","operators"],functions:[],excludeFilter:[],defaultColFilter:[],defaultAnyFilter:b.getColumnData(c,E.filter_defaultFilter,D.columns,!0)||""};for(F.parsed=D.$headers.map(function(d){return D.parsers&&D.parsers[d]&&D.parsers[d].parsed||b.getData&&"parsed"===b.getData(D.$headerIndexed[d],b.getColumnData(c,D.headers,d),"filter")||a(this).hasClass("filter-parsed")}).get(),m=0;m1&&(z=parseInt(y[0],10)-1,z>=0&&zt;t++)s=d[t]||"",v||(t=m),v=!(!v||!p.length||0!==s.indexOf(p[t]||"")||C.alreadyFiltered.test(s)||/[=\"\|!]/.test(s)||/(>=?\s*-\d)/.test(s)||/(<=?\s*\d)/.test(s)||""!==s&&D.$filters&&D.$filters.eq(t).find("select").length&&!D.$headerIndexed[t].hasClass("filter-match"));for(u=i.not("."+E.filter_filteredRow).length,v&&0===u&&(v=!1),D.debug&&b.log("Filter: Searching through "+(v&&f>u?u:"all")+" rows"),F.anyMatchFlag&&(D.sortLocaleCompare&&(F.anyMatchFilter=b.replaceAccents(F.anyMatchFilter)),E.filter_defaultFilter&&C.iQuery.test(G.defaultAnyFilter)&&(F.anyMatchFilter=b.filter.defaultFilter(F.anyMatchFilter,G.defaultAnyFilter),v=!1),F.iAnyMatchFilter=E.filter_ignoreCase&&D.ignoreCase?F.anyMatchFilter.toLowerCase():F.anyMatchFilter),j=0;f>j;j++)if(A=i[j].className,n=j&&C.child.test(A),!(n||v&&C.filtered.test(A))){if(F.$row=i.eq(j),F.cacheArray=g[j],h=F.cacheArray[D.columns],F.rawArray=h.raw,F.childRowText="",!E.filter_childByColumn){for(A="",o=h.child,t=0;t")>=0)return o;a.isArray(o)?l=o:"object"===a.type(m)&&o&&(l=o(c,d,e))}if(l===!1&&(l=b.filter.getOptions(c,d,e)),l=a.grep(l,function(b,c){return a.inArray(b,l)===c}),i.$headerIndexed[d].hasClass("filter-select-nosort"))return l;for(h=l.length,g=0;h>g;g++)k.push({t:l[g],p:i.parsers&&i.parsers[d].format(l[g],c,[],d)});for(f=i.textSorter||"",k.sort(function(e,g){var h=e.p.toString(),i=g.p.toString();return a.isFunction(f)?f(h,i,!0,d,c):"object"==typeof f&&f.hasOwnProperty(d)?f[d](h,i,!0,d,c):b.sortNatural?b.sortNatural(h,i):!0}),l=[],h=k.length,g=0;h>g;g++)l.push(k[g].t);return l},getOptions:function(b,c,d){b=a(b)[0];var e,f,g,h,i,j=b.config,k=j.widgetOptions,l=[];for(f=0;fe;e++)h=i.row?i.row[e]:i.normalized[e][j.columns].$row[0],d&&h.className.match(k.filter_filteredRow)||(k.filter_useParsedData||j.parsers[c].parsed||j.$headerIndexed[c].hasClass("filter-parsed")?l.push(""+i.normalized[e][c]):l.push(i.normalized[e][j.columns].raw[c]));return l},buildSelect:function(d,e,f,g,h){if(d=a(d)[0],e=parseInt(e,10),d.config.cache&&!a.isEmptyObject(d.config.cache)){var i,j,k,l,m,n,o=d.config,p=o.widgetOptions,q=o.$headerIndexed[e],r='",s=o.$table.find("thead").find("select."+c.filter+'[data-column="'+e+'"]').val();if(("undefined"==typeof f||""===f)&&(f=b.filter.getOptionSource(d,e,h)),a.isArray(f)){for(i=0;i=0&&(l=k.split(p.filter_selectSourceSeparator),j=l[0],k=l[1]),r+=""!==f[i]?"":"";f=[]}m=(o.$filters?o.$filters:o.$table.children("thead")).find("."+c.filter),p.filter_$externalFilters&&(m=m&&m.length?m.add(p.filter_$externalFilters):p.filter_$externalFilters),n=m.filter('select[data-column="'+e+'"]'),n.length&&(n[g?"html":"append"](r),a.isArray(f)||n.append(f).val(s),n.val(s))}},buildDefault:function(a,c){var d,e,f,g=a.config,h=g.widgetOptions,i=g.columns;for(d=0;i>d;d++)e=g.$headerIndexed[d],f=!(e.hasClass("filter-false")||e.hasClass("parser-false")),(e.hasClass("filter-select")||b.getColumnData(a,h.filter_functions,d)===!0)&&f&&b.filter.buildSelect(a,d,"",c,e.hasClass(h.filter_onlyAvail))}},b.getFilters=function(d,e,f,g){var h,i,j,k,l=!1,m=d?a(d)[0].config:"",n=m?m.widgetOptions:"";if(e!==!0&&n&&!n.filter_columnFilters||a.isArray(f)&&f.join("")===m.lastCombinedFilter)return a(d).data("lastSearch");if(m&&(m.$filters&&(i=m.$filters.find("."+c.filter)),n.filter_$externalFilters&&(i=i&&i.length?i.add(n.filter_$externalFilters):n.filter_$externalFilters),i&&i.length))for(l=f||[],h=0;h1&&(j=j.slice(1)),h===m.columns&&(k=j.filter(n.filter_anyColumnSelector),j=k.length?k:j),j.val(f[h]).trigger("change.tsfilter")):(l[h]=j.val()||"",h===m.columns?j.slice(1).filter('[data-column*="'+j.attr("data-column")+'"]').val(l[h]):j.slice(1).val(l[h])),h===m.columns&&j.length&&(n.filter_$anyMatch=j));return 0===l.length&&(l=!1),l},b.setFilters=function(c,d,e,f){var g=c?a(c)[0].config:"",h=b.getFilters(c,!0,d,f);return g&&e&&(g.lastCombinedFilter=null,g.lastSearch=[],b.filter.searching(g.table,d,f),g.$table.trigger("filterFomatterUpdate")),!!h}}(jQuery),function(a,b){"use strict";var c=a.tablesorter||{};a.extend(c.css,{sticky:"tablesorter-stickyHeader",stickyVis:"tablesorter-sticky-visible",stickyHide:"tablesorter-sticky-hidden", +stickyWrap:"tablesorter-sticky-wrapper"}),c.addHeaderResizeEvent=function(b,c,d){if(b=a(b)[0],b.config){var e={timer:250},f=a.extend({},e,d),g=b.config,h=g.widgetOptions,i=function(a){var b,c,d,e,f,i,j=g.$headers.length;for(h.resize_flag=!0,c=[],b=0;j>b;b++)d=g.$headers.eq(b),e=d.data("savedSizes")||[0,0],f=d[0].offsetWidth,i=d[0].offsetHeight,(f!==e[0]||i!==e[1])&&(d.data("savedSizes",[f,i]),c.push(d[0]));c.length&&a!==!1&&g.$table.trigger("resize",[c]),h.resize_flag=!1};return i(!1),clearInterval(h.resize_timer),c?(h.resize_flag=!1,!1):void(h.resize_timer=setInterval(function(){h.resize_flag||i()},f.timer))}},c.addWidget({id:"stickyHeaders",priority:60,options:{stickyHeaders:"",stickyHeaders_attachTo:null,stickyHeaders_xScroll:null,stickyHeaders_yScroll:null,stickyHeaders_offset:0,stickyHeaders_filteredToTop:!0,stickyHeaders_cloneId:"-sticky",stickyHeaders_addResizeEvent:!0,stickyHeaders_includeCaption:!0,stickyHeaders_zIndex:2},format:function(d,e,f){if(!(e.$table.hasClass("hasStickyHeaders")||a.inArray("filter",e.widgets)>=0&&!e.$table.hasClass("hasFilters"))){var g,h,i,j,k=e.$table,l=a(f.stickyHeaders_attachTo),m=e.namespace+"stickyheaders ",n=a(f.stickyHeaders_yScroll||f.stickyHeaders_attachTo||b),o=a(f.stickyHeaders_xScroll||f.stickyHeaders_attachTo||b),p=k.children("thead:first"),q=p.children("tr").not(".sticky-false").children(),r=k.children("tfoot"),s=isNaN(f.stickyHeaders_offset)?a(f.stickyHeaders_offset):"",t=s.length?s.height()||0:parseInt(f.stickyHeaders_offset,10)||0,u=k.parent().closest("."+c.css.table).hasClass("hasStickyHeaders")?k.parent().closest("table.tablesorter")[0].config.widgetOptions.$sticky.parent():[],v=u.length?u.height():0,w=f.$sticky=k.clone().addClass("containsStickyHeaders "+c.css.sticky+" "+f.stickyHeaders+" "+e.namespace.slice(1)+"_extra_table").wrap('
'),x=w.parent().addClass(c.css.stickyHide).css({position:l.length?"absolute":"fixed",padding:parseInt(w.parent().parent().css("padding-left"),10),top:t+v,left:0,visibility:"hidden",zIndex:f.stickyHeaders_zIndex||2}),y=w.children("thead:first"),z="",A=0,B=function(a,c){var d,e,f,g,h,i=a.filter(":visible"),j=i.length;for(d=0;j>d;d++)g=c.filter(":visible").eq(d),h=i.eq(d),"border-box"===h.css("box-sizing")?e=h.outerWidth():"collapse"===g.css("border-collapse")?b.getComputedStyle?e=parseFloat(b.getComputedStyle(h[0],null).width):(f=parseFloat(h.css("border-width")),e=h.outerWidth()-parseFloat(h.css("padding-left"))-parseFloat(h.css("padding-right"))-f):e=h.width(),g.css({width:e,"min-width":e,"max-width":e})},C=function(){t=s.length?s.height()||0:parseInt(f.stickyHeaders_offset,10)||0,A=0,x.css({left:l.length?parseInt(l.css("padding-left"),10)||0:k.offset().left-parseInt(k.css("margin-left"),10)-o.scrollLeft()-A,width:k.outerWidth()}),B(k,w),B(q,j)},D=function(b){if(k.is(":visible")){v=u.length?u.offset().top-n.scrollTop()+u.height():0;var d=k.offset(),e=a.isWindow(n[0]),f=a.isWindow(o[0]),g=(l.length?e?n.scrollTop():n.offset().top:n.scrollTop())+t+v,h=k.height()-(x.height()+(r.height()||0)),i=g>d.top&&gg;g++)e.onRenderHeader.apply(i.eq(g),[g,e,w]);o.add(n).unbind("scroll resize ".split(" ").join(m).replace(/\s+/g," ")).bind("scroll resize ".split(" ").join(m),function(a){D("resize"===a.type)}),e.$table.unbind("stickyHeadersUpdate"+m).bind("stickyHeadersUpdate"+m,function(){D(!0)}),f.stickyHeaders_addResizeEvent&&c.addHeaderResizeEvent(d),k.hasClass("hasFilters")&&f.filter_columnFilters&&(k.bind("filterEnd"+m,function(){var d=a(document.activeElement).closest("td"),g=d.parent().children().index(d);x.hasClass(c.css.stickyVis)&&f.stickyHeaders_filteredToTop&&(b.scrollTo(0,k.position().top),g>=0&&e.$filters&&e.$filters.eq(g).find("a, select, input").filter(":visible").focus())}),c.filter.bindSearch(k,j.find("."+c.css.filter)),f.filter_hideFilters&&c.filter.hideFilters(w,e)),k.trigger("stickyHeadersInit")}},remove:function(d,e,f){var g=e.namespace+"stickyheaders ";e.$table.removeClass("hasStickyHeaders").unbind("pagerComplete filterEnd stickyHeadersUpdate ".split(" ").join(g).replace(/\s+/g," ")).next("."+c.css.stickyWrap).remove(),f.$sticky&&f.$sticky.length&&f.$sticky.remove(),a(b).add(f.stickyHeaders_xScroll).add(f.stickyHeaders_yScroll).add(f.stickyHeaders_attachTo).unbind("scroll resize ".split(" ").join(g).replace(/\s+/g," ")),c.addHeaderResizeEvent(d,!1)}})}(jQuery,window),function(a,b){"use strict";var c=a.tablesorter||{};a.extend(c.css,{resizableContainer:"tablesorter-resizable-container",resizableHandle:"tablesorter-resizable-handle",resizableNoSelect:"tablesorter-disableSelection",resizableStorage:"tablesorter-resizable"}),a(function(){var b="";a(b).appendTo("body")}),c.resizable={init:function(b,d){if(!b.$table.hasClass("hasResizable")){b.$table.addClass("hasResizable"),c.resizableReset(b.table,!0),d.resizable_={$wrap:b.$table.parent(),mouseXPosition:0,$target:null,$next:null,overflow:"auto"===b.$table.parent().css("overflow"),fullWidth:Math.abs(b.$table.parent().width()-b.$table.width())<20,storedSizes:[]};var e,f,g,h,i=parseInt(b.$table.css("margin-top"),10);for(d.resizable_.storedSizes=h=(c.storage&&d.resizable!==!1?c.storage(b.table,c.css.resizableStorage):[])||[],c.resizable.setWidths(b,d,h),d.$resizable_container=a('
').css({top:i}).insertBefore(b.$table),g=0;g').appendTo(d.$resizable_container).attr({"data-column":g,unselectable:"on"}).data("header",f).bind("selectstart",!1);b.$table.one("tablesorter-initialized",function(){c.resizable.setHandlePosition(b,d),c.resizable.bindings(this.config,this.config.widgetOptions)})}},setWidth:function(a,b){a.css({width:b,"min-width":"","max-width":""})},setWidths:function(b,d,e){var f,g=a(b.namespace+"_extra_headers"),h=b.$table.children("colgroup").children("col");if(e=e||d.resizable_.storedSizes||[],e.length){for(f=0;ff||f===h&&d.resizable_addLastColumn)&&c.css({display:"inline-block",height:g,left:j.position().left-e+j.outerWidth()-i}):c.hide())})},toggleTextSelection:function(b,d){var e=b.namespace+"tsresize";b.widgetOptions.resizable_.disabled=d,a("body").toggleClass(c.css.resizableNoSelect,d),d?a("body").attr("unselectable","on").bind("selectstart"+e,!1):a("body").removeAttr("unselectable").unbind("selectstart"+e)},bindings:function(d,e){var f=d.namespace+"tsresize";e.$resizable_container.children().bind("mousedown",function(b){var f,g,h=e.resizable_,i=a(d.namespace+"_extra_headers"),j=a(b.target).data("header");for(f=parseInt(j.attr("data-column"),10),h.$target=j=j.add(i.filter('[data-column="'+f+'"]')),h.target=f,h.$next=b.shiftKey||e.resizable_targetLast?j.parent().children().not(".resizable-false").filter(":last"):j.nextAll(":not(.resizable-false)").eq(0),f=parseInt(h.$next.attr("data-column"),10),h.$next=h.$next.add(i.filter('[data-column="'+f+'"]')),h.next=f,h.mouseXPosition=b.pageX,h.storedSizes=[],f=0;f0?d.sortList=k:c.hasInitialized&&k&&k.length>0&&i.trigger("sorton",[k]))},remove:function(a,c){c.$table.removeClass("hasSaveSort"),b.storage&&b.storage(a,"tablesorter-savesort","")}})}(jQuery),a.tablesorter}); Index: lams_central/web/includes/javascript/jquery.tablesorter.js =================================================================== diff -u -ra1b4a3143714e2704412c585131a93fee2d8c40b -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_central/web/includes/javascript/jquery.tablesorter.js (.../jquery.tablesorter.js) (revision a1b4a3143714e2704412c585131a93fee2d8c40b) +++ lams_central/web/includes/javascript/jquery.tablesorter.js (.../jquery.tablesorter.js) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -1,5 +1,3 @@ -/*! -* TableSorter (FORK) 2.18.4 min - Client-side table sorting with ease! -* Copyright (c) 2007 Christian Bach; fork maintained by Rob Garrison -*/ -!function(h){h.extend({tablesorter:new function(){function d(){var b=arguments[0],a=1':"";n.$headers=h(h.map(h(b).find(n.selectorHeaders),function(l,d){c=h(l);if(!c.parent().hasClass(n.cssIgnoreRow))return a=g.getColumnData(b,n.headers,d,!0),n.headerContent[d]=c.html(),""!==n.headerTemplate&&(m=n.headerTemplate.replace(/\{content\}/g, c.html()).replace(/\{icon\}/g,e),n.onRenderTemplate&&(f=n.onRenderTemplate.apply(c,[d,m]))&&"string"===typeof f&&(m=f),c.html('
'+m+"
")),n.onRenderHeader&&n.onRenderHeader.apply(c,[d,n,n.$table]),l.column=parseInt(c.attr("data-column"),10),l.order=F(g.getData(c,a,"sortInitialOrder")||n.sortInitialOrder)?[1,0,2]:[0,1,2],l.count=-1,l.lockedOrder=!1,x=g.getData(c,a,"lockedOrder")||!1,"undefined"!==typeof x&&!1!==x&&(l.order=l.lockedOrder=F(x)?[1,1,1]:[0,0,0]),c.addClass(g.css.header+ " "+n.cssHeader),n.headerList[d]=l,c.parent().addClass(g.css.headerRow+" "+n.cssHeaderRow).attr("role","row"),n.tabIndex&&c.attr("tabindex",0),l}));h(b).find(n.selectorHeaders).attr({scope:"col",role:"columnheader"});H(b);n.debug&&(r("Built headers:",l),d(n.$headers))}function I(b,a,c){var f=b.config;f.$table.find(f.selectorRemove).remove();p(b);y(b);J(f.$table,a,c)}function H(b){var a,c,f,e=b.config;e.$headers.each(function(m,d){c=h(d);f=g.getColumnData(b,e.headers,m,!0);a="false"===g.getData(d, f,"sorter")||"false"===g.getData(d,f,"parser");d.sortDisabled=a;c[a?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+a);b.id&&(a?c.removeAttr("aria-controls"):c.attr("aria-controls",b.id))})}function G(b){var a,c,f=b.config,e=f.sortList,m=e.length,d=g.css.sortNone+" "+f.cssNone,l=[g.css.sortAsc+" "+f.cssAsc,g.css.sortDesc+" "+f.cssDesc],n=[f.cssIconAsc,f.cssIconDesc,f.cssIconNone],w=["ascending","descending"],k=h(b).find("tfoot tr").children().add(f.$extraHeaders).removeClass(l.join(" ")); f.$headers.removeClass(l.join(" ")).addClass(d).attr("aria-sort","none").find("."+f.cssIcon).removeClass(n.join(" ")).addClass(n[2]);for(a=0;a"),c=h(b).width(),h(b.tBodies).not("."+f.cssInfoBlock).find("tr:first").children(":visible").each(function(){a.append(h("").css("width",parseInt(h(this).width()/ c*1E3,10)/10+"%"))}),f.$table.prepend(a))}function R(b,a){var c,f,e,m,g,l=b.config,d=a||l.sortList;l.sortList=[];h.each(d,function(b,a){m=parseInt(a[0],10);if(e=l.$headers.filter('[data-column="'+m+'"]:last')[0]){f=(f=(""+a[1]).match(/^(1|d|s|o|n)/))?f[0]:"";switch(f){case "1":case "d":f=1;break;case "s":f=g||0;break;case "o":c=e.order[(g||0)%(l.sortReset?3:2)];f=0===c?1:1===c?0:2;break;case "n":e.count+=1;f=e.order[e.count%(l.sortReset?3:2)];break;default:f=0}g=0===b?f:g;c=[m,parseInt(f,10)||0]; l.sortList.push(c);f=h.inArray(c[1],e.order);e.count=0<=f?f:c[1]%(l.sortReset?3:2)}})}function S(b,a){return b&&b[a]?b[a].type||"":""}function N(b,a,c){if(b.isUpdating)return setTimeout(function(){N(b,a,c)},50);var f,e,m,d,l=b.config,n=!c[l.sortMultiSortKey],w=l.$table;w.trigger("sortStart",b);a.count=c[l.sortResetKey]?2:(a.count+1)%(l.sortReset?3:2);l.sortRestart&&(e=a,l.$headers.each(function(){this===e||!n&&h(this).is("."+g.css.sortDesc+",."+g.css.sortAsc)||(this.count=-1)}));e=parseInt(h(a).attr("data-column"), 10);if(n){l.sortList=[];if(null!==l.sortForce)for(f=l.sortForce,m=0;mf&&(l.sortList.push([e,f]),1f&&(l.sortList.push([e,f]),1 thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]}; g.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",info:"tablesorter-infoOnly",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"};g.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ", nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"};g.log=d;g.benchmark=r;g.construct=function(b){return this.each(function(){var a=h.extend(!0,{},g.defaults,b);a.originalSettings=b;!this.hasInitialized&&g.buildTable&&"TABLE"!==this.tagName?g.buildTable(this,a):g.setup(this,a)})};g.setup=function(b,a){if(!b||!b.tHead||0===b.tBodies.length||!0===b.hasInitialized)return a.debug?d("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"): "";var c="",f=h(b),e=h.metadata;b.hasInitialized=!1;b.isProcessing=!0;b.config=a;h.data(b,"tablesorter",a);a.debug&&h.data(b,"startoveralltimer",new Date);a.supportsDataObject=function(a){a[0]=parseInt(a[0],10);return 1'),c=h.fn.detach?a.detach():a.remove();c=h(b).find("span.tablesorter-savemyplace");a.insertAfter(c);c.remove();b.isProcessing=!1};g.clearTableBody=function(b){h(b)[0].config.$tbodies.children().detach()};g.bindEvents=function(b,a,c){b=h(b)[0];var f, e=b.config;!0!==c&&(e.$extraHeaders=e.$extraHeaders?e.$extraHeaders.add(a):a);a.find(e.selectorSort).add(a.filter(e.selectorSort)).unbind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" ")).bind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" "),function(c,d){var g;g=c.type;if(!(1!==(c.which||c.button)&&!/sort|keyup/.test(g)||"keyup"===g&&13!==c.which||"mouseup"===g&&!0!==d&&250<(new Date).getTime()-f)){if("mousedown"===g)return f=(new Date).getTime(),/(input|select|button|textarea)/i.test(c.target.tagName)|| h(c.target).closest("td,th").hasClass(e.cssAllowClicks)?"":!e.cancelSelection;e.delayInit&&k(e.cache)&&y(b);g=h.fn.closest?h(this).closest("th, td")[0]:/TH|TD/.test(this.tagName)?this:h(this).parents("th, td")[0];g=e.$headers[a.index(g)];g.sortDisabled||N(b,g,c)}});e.cancelSelection&&a.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})};g.restoreHeaders=function(b){var a=h(b)[0].config;a.$table.find(a.selectorHeaders).each(function(b){h(this).find("."+ g.css.headerIn).length&&h(this).html(a.headerContent[b])})};g.destroy=function(b,a,c){b=h(b)[0];if(b.hasInitialized){g.refreshWidgets(b,!0,!0);var f=h(b),e=b.config,d=f.find("thead:first"),k=d.find("tr."+g.css.headerRow).removeClass(g.css.headerRow+" "+e.cssHeaderRow),l=f.find("tfoot:first > tr").children("th, td");!1===a&&0<=h.inArray("uitheme",e.widgets)&&(f.trigger("applyWidgetId",["uitheme"]),f.trigger("applyWidgetId",["zebra"]));d.find("tr").not(k).remove();f.removeData("tablesorter").unbind("sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState ".split(" ").join(e.namespace+ " "));e.$headers.add(l).removeClass([g.css.header,e.cssHeader,e.cssAsc,e.cssDesc,g.css.sortAsc,g.css.sortDesc,g.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true");k.find(e.selectorSort).unbind(["mousedown","mouseup","keypress",""].join(e.namespace+" "));g.restoreHeaders(b);f.toggleClass(g.css.table+" "+e.tableClass+" tablesorter-"+e.theme,!1===a);b.hasInitialized=!1;delete b.config.cache;"function"===typeof c&&c(b)}};g.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i};g.sortNatural=function(b,a){if(b===a)return 0;var c,f,e,d,k,l;f=g.regex;if(f.hex.test(a)){c=parseInt(b.match(f.hex),16);e=parseInt(a.match(f.hex),16);if(ce)return 1}c=b.replace(f.chunk,"\\0$1\\0").replace(f.chunks,"").split("\\0");f=a.replace(f.chunk,"\\0$1\\0").replace(f.chunks,"").split("\\0");l=Math.max(c.length,f.length);for(k=0;kd)return 1}return 0};g.sortNaturalAsc=function(b,a,c,f,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:-c||-1:""===a&&0!==c?"boolean"===typeof c?c?1:-1:c||1:g.sortNatural(b,a)};g.sortNaturalDesc=function(b,a,c,f,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:c||1:""===a&&0!==c?"boolean"===typeof c?c? 1:-1:-c||-1:g.sortNatural(a,b)};g.sortText=function(b,a){return b>a?1:bh.inArray(r[f].id,k))&&(e.debug&&d('Refeshing widgets: Removing "'+r[f].id+'"'),r[f].hasOwnProperty("remove")&&e.widgetInit[r[f].id]&&(r[f].remove(b,e,e.widgetOptions),e.widgetInit[r[f].id]=!1));!0!==c&&g.applyWidget(b,a)};g.getData=function(b, a,c){var d="";b=h(b);var e,g;if(!b.length)return"";e=h.metadata?b.metadata():!1;g=" "+(b.attr("class")||"");"undefined"!==typeof b.data(c)||"undefined"!==typeof b.data(c.toLowerCase())?d+=b.data(c)||b.data(c.toLowerCase()):e&&"undefined"!==typeof e[c]?d+=e[c]:a&&"undefined"!==typeof a[c]?d+=a[c]:" "!==g&&g.match(" "+c+"-")&&(d=g.match(new RegExp("\\s"+c+"-([\\w-]+)"))[1]||"");return h.trim(d)};g.formatFloat=function(b,a){if("string"!==typeof b||""===b)return b;var c;b=(a&&a.config?!1!==a.config.usNumberFormat: "undefined"!==typeof a?a:1)?b.replace(/,/g,""):b.replace(/[\s|\.]/g,"").replace(/,/g,".");/^\s*\([.\d]+\)/.test(b)&&(b=b.replace(/^\s*\(([.\d]+)\)/,"-$1"));c=parseFloat(b);return isNaN(c)?h.trim(b):c};g.isDigit=function(b){return isNaN(b)?/^[\-+(]?\d+[)]?$/.test(b.toString().replace(/[,.'"\s]/g,"")):!0}}});var p=h.tablesorter;h.fn.extend({tablesorter:p.construct});p.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"});p.addParser({id:"text",is:function(){return!0}, format:function(d,r){var k=r.config;d&&(d=h.trim(k.ignoreCase?d.toLocaleLowerCase():d),d=k.sortLocaleCompare?p.replaceAccents(d):d);return d},type:"text"});p.addParser({id:"digit",is:function(d){return p.isDigit(d)},format:function(d,r){var k=p.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),r);return d&&"number"===typeof k?k:d?h.trim(d&&r.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});p.addParser({id:"currency",is:function(d){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((d|| "").replace(/[+\-,. ]/g,""))},format:function(d,r){var k=p.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),r);return d&&"number"===typeof k?k:d?h.trim(d&&r.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});p.addParser({id:"url",is:function(d){return/^(https?|ftp|file):\/\//.test(d)},format:function(d){return d?h.trim(d.replace(/(https?|ftp|file):\/\//,"")):d},parsed:!0,type:"text"});p.addParser({id:"isoDate",is:function(d){return/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/.test(d)},format:function(d, h){var k=d?new Date(d.replace(/-/g,"/")):d;return k instanceof Date&&isFinite(k)?k.getTime():d},type:"numeric"});p.addParser({id:"percent",is:function(d){return/(\d\s*?%|%\s*?\d)/.test(d)&&15>d.length},format:function(d,h){return d?p.formatFloat(d.replace(/%/g,""),h):d},type:"numeric"});p.addParser({id:"image",is:function(d,h,k,p){return 01?Array.prototype.slice.call(arguments):a;"undefined"!=typeof console&&"undefined"!=typeof console.log?console[/error/i.test(a)?"error":/warn/i.test(a)?"warn":"log"](b):alert(b)}function c(a,c){b(a+" ("+((new Date).getTime()-c.getTime())+"ms)")}function d(a){for(var b in a)return!1;return!0}function e(c,d,e,f){for(var g,h,i=c.config,j=v.parsers.length,k=!1,l="",m=!0;""===l&&m;)e++,d[e]?(k=d[e].cells[f],l=v.getElementText(i,k,f),h=a(k),c.config.debug&&b("Checking if value was empty on row "+e+", column: "+f+': "'+l+'"')):m=!1;for(;--j>=0;)if(g=v.parsers[j],g&&"text"!==g.id&&g.is&&g.is(l,c,k,h))return g;return v.getParserById("text")}function f(a,b,c,d){"undefined"==typeof d&&(d=v.getElementText(a,b,c));var e=""+d,f=a.parsers[c],g=a.extractors[c];return f&&(g&&"function"==typeof g.format&&(d=g.format(d,a.table,b,c)),e="no-parser"===f.id?"":f.format(""+d,a.table,b,c),a.ignoreCase&&"string"==typeof e&&(e=e.toLowerCase())),e}function g(a){var d,f,g,h,i,j,k,l,m,n,o=a.config,p=o.$tbodies=o.$table.children("tbody:not(."+o.cssInfoBlock+")"),q=0,r="",s=p.length;if(0===s)return o.debug?b("Warning: *Empty table!* Not building a parser cache"):"";for(o.debug&&(n=new Date,b("Detecting parsers for each column")),f={extractors:[],parsers:[]};s>q;){if(d=p[q].rows,d.length)for(g=o.columns,h=0;g>h;h++)i=o.$headerIndexed[h],j=v.getColumnData(a,o.headers,h),m=v.getParserById(v.getData(i,j,"extractor")),l=v.getParserById(v.getData(i,j,"sorter")),k="false"===v.getData(i,j,"parser"),o.empties[h]=(v.getData(i,j,"empty")||o.emptyTo||(o.emptyToBottom?"bottom":"top")).toLowerCase(),o.strings[h]=(v.getData(i,j,"string")||o.stringTo||"max").toLowerCase(),k&&(l=v.getParserById("no-parser")),m||(m=!1),l||(l=e(a,d,-1,h)),o.debug&&(r+="column:"+h+"; extractor:"+m.id+"; parser:"+l.id+"; string:"+o.strings[h]+"; empty: "+o.empties[h]+"\n"),f.parsers[h]=l,f.extractors[h]=m;q+=f.parsers.length?s:1}o.debug&&(b(r?r:"No parsers detected"),c("Completed detecting parsers",n)),o.parsers=f.parsers,o.extractors=f.extractors}function h(d){var e,g,h,i,j,k,l,m,n,o,p,q,r,s=d.config,t=s.$tbodies,u=s.parsers;if(s.cache={},s.totalRows=0,!u)return s.debug?b("Warning: *Empty table!* Not building a cache"):"";for(s.debug&&(n=new Date),s.showProcessing&&v.isProcessing(d,!0),k=0;ki;++i)if(p={child:[],raw:[]},l=a(t[k].rows[i]),m=[],l.hasClass(s.cssChildRow)&&0!==i)for(g=e.normalized.length-1,q=e.normalized[g][s.columns],q.$row=q.$row.add(l),l.prev().hasClass(s.cssChildRow)||l.prev().addClass(v.css.cssHasChild),h=l.children("th, td"),g=q.child.length,q.child[g]=[],j=0;ji;i++)o.push(e[i][l.columns].$row),l.appender&&(!l.pager||l.pager.removeRows&&m.pager_removeRows||l.pager.ajax)||h.append(e[i][l.columns].$row);v.processTbody(a,h,!1)}l.appender&&l.appender(a,o),l.debug&&c("Rebuilt table",k),b||l.appender||v.applyWidget(a),a.isUpdating&&l.$table.trigger("updateComplete",a)}function j(a){return/^d/i.test(a)||1===a}function k(d){var e,f,g,h,i,k,l,n,o=d.config;for(o.headerList=[],o.headerContent=[],o.debug&&(l=new Date),o.columns=v.computeColumnIndex(o.$table.children("thead, tfoot").children("tr")),h=o.cssIcon?'':"",o.$headers=a(a.map(a(d).find(o.selectorHeaders),function(b,c){return f=a(b),f.parent().hasClass(o.cssIgnoreRow)?void 0:(e=v.getColumnData(d,o.headers,c,!0),o.headerContent[c]=f.html(),""===o.headerTemplate||f.find("."+v.css.headerIn).length||(i=o.headerTemplate.replace(/\{content\}/g,f.html()).replace(/\{icon\}/g,f.find("."+v.css.icon).length?"":h),o.onRenderTemplate&&(g=o.onRenderTemplate.apply(f,[c,i]),g&&"string"==typeof g&&(i=g)),f.html('
'+i+"
")),o.onRenderHeader&&o.onRenderHeader.apply(f,[c,o,o.$table]),b.column=parseInt(f.attr("data-column"),10),b.order=j(v.getData(f,e,"sortInitialOrder")||o.sortInitialOrder)?[1,0,2]:[0,1,2],b.count=-1,b.lockedOrder=!1,k=v.getData(f,e,"lockedOrder")||!1,"undefined"!=typeof k&&k!==!1&&(b.order=b.lockedOrder=j(k)?[1,1,1]:[0,0,0]),f.addClass(v.css.header+" "+o.cssHeader),o.headerList[c]=b,f.parent().addClass(v.css.headerRow+" "+o.cssHeaderRow).attr("role","row"),o.tabIndex&&f.attr("tabindex",0),b)})),o.$headerIndexed=[],n=0;nb;b++)d=f.$headers.eq(b),e=v.getColumnData(a,f.headers,b,!0),c="false"===v.getData(d,e,"sorter")||"false"===v.getData(d,e,"parser"),d[0].sortDisabled=c,d[c?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+c),a.id&&(c?d.removeAttr("aria-controls"):d.attr("aria-controls",a.id))}function n(b){var c,d,e,f,g,h,i,j,k=b.config,l=k.sortList,m=l.length,n=v.css.sortNone+" "+k.cssNone,o=[v.css.sortAsc+" "+k.cssAsc,v.css.sortDesc+" "+k.cssDesc],p=[k.cssIconAsc,k.cssIconDesc,k.cssIconNone],q=["ascending","descending"],r=a(b).find("tfoot tr").children().add(a(k.namespace+"_extra_headers")).removeClass(o.join(" "));for(k.$headers.removeClass(o.join(" ")).addClass(n).attr("aria-sort","none").find("."+v.css.icon).removeClass(p.join(" ")).addClass(p[2]),e=0;m>e;e++)if(2!==l[e][1]&&(c=k.$headers.not(".sorter-false").filter('[data-column="'+l[e][0]+'"]'+(1===m?":last":"")),c.length)){for(f=0;fe;e++)h=g.eq(e),h.length&&(d=g[e],i=d.order[(d.count+1)%(k.sortReset?3:2)],j=a.trim(h.text())+": "+v.language[h.hasClass(v.css.sortAsc)?"sortAsc":h.hasClass(v.css.sortDesc)?"sortDesc":"sortNone"]+v.language[0===i?"nextAsc":1===i?"nextDesc":"nextNone"],h.attr("aria-label",j))}function o(b,c){var d,e,f,g,h,i,j,k,l=b.config,m=c||l.sortList,n=m.length;for(l.sortList=[],h=0;n>h;h++)if(k=m[h],d=parseInt(k[0],10),d=0?e:f[1]%(l.sortReset?3:2)}}function p(a,b){return a&&a[b]?a[b].type||"":""}function q(b,c,d){if(b.isUpdating)return setTimeout(function(){q(b,c,d)},50);var e,f,g,h,j,k,l,m=b.config,o=!d[m.sortMultiSortKey],p=m.$table,s=m.$headers.length;if(p.trigger("sortStart",b),c.count=d[m.sortResetKey]?2:(c.count+1)%(m.sortReset?3:2),m.sortRestart)for(f=c,g=0;s>g;g++)l=m.$headers.eq(g),l[0]===f||!o&&l.is("."+v.css.sortDesc+",."+v.css.sortAsc)||(l[0].count=-1);if(f=parseInt(a(c).attr("data-column"),10),o){if(m.sortList=[],null!==m.sortForce)for(e=m.sortForce,h=0;hj&&(m.sortList.push([f,j]),c.colSpan>1))for(h=1;h1)for(h=0;h=0&&m.sortList.splice(k,1);if(v.isValueInArray(f,m.sortList)>=0)for(h=0;hj&&(m.sortList.push([f,j]),c.colSpan>1))for(h=1;he;e++)i=q.cache[e].colMax,j=q.cache[e].normalized,j.sort(function(c,d){for(b=0;t>b;b++){if(g=s[b][0],k=s[b][1],o=0===k,q.sortStable&&c[g]===d[g]&&1===t)return c[q.columns].order-d[q.columns].order;if(f=/n/i.test(p(q.parsers,g)),f&&q.strings[g]?(f="boolean"==typeof q.string[q.strings[g]]?(o?1:-1)*(q.string[q.strings[g]]?-1:1):q.strings[g]?q.string[q.strings[g]]||0:0,l=q.numberSorter?q.numberSorter(c[g],d[g],o,i[g],a):v["sortNumeric"+(o?"Asc":"Desc")](c[g],d[g],f,i[g],g,a)):(m=o?c:d,n=o?d:c,l="function"==typeof r?r(m[g],n[g],o,g,a):"object"==typeof r&&r.hasOwnProperty(g)?r[g](m[g],n[g],o,g,a):v["sortNatural"+(o?"Asc":"Desc")](c[g],d[g],g,a,q)),l)return l}return c[q.columns].order-d[q.columns].order});q.debug&&c("Sorting on "+s.toString()+" and dir "+k+" time",h)}}function s(b,c){b.table.isUpdating&&b.$table.trigger("updateComplete",b.table),a.isFunction(c)&&c(b.table)}function t(b,c,d){var e=a.isArray(c)?c:b.sortList,f="undefined"==typeof c?b.resort:c;f===!1||b.serverSideSorting||b.table.isProcessing?(s(b,d),v.applyWidget(b.table,!1)):e.length?b.$table.trigger("sorton",[e,function(){s(b,d)},!0]):b.$table.trigger("sortReset",[function(){s(b,d),v.applyWidget(b.table,!1)}])}function u(b){var c=b.config,e=c.$table,j="sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(c.namespace+" ");e.unbind(j.replace(/\s+/g," ")).bind("sortReset"+c.namespace,function(d,e){d.stopPropagation(),c.sortList=[],n(b),r(b),i(b),a.isFunction(e)&&e(b)}).bind("updateAll"+c.namespace,function(a,d,e){a.stopPropagation(),b.isUpdating=!0,v.refreshWidgets(b,!0,!0),k(b),v.bindEvents(b,c.$headers,!0),u(b),l(b,d,e)}).bind("update"+c.namespace+" updateRows"+c.namespace,function(a,c,d){a.stopPropagation(),b.isUpdating=!0,m(b),l(b,c,d)}).bind("updateCell"+c.namespace,function(d,g,h,i){d.stopPropagation(),b.isUpdating=!0,e.find(c.selectorRemove).remove();var j,k,l,m,n=c.$tbodies,o=a(g),p=n.index(a.fn.closest?o.closest("tbody"):o.parents("tbody").filter(":first")),q=c.cache[p],r=a.fn.closest?o.closest("tr"):o.parents("tr").filter(":first");g=o[0],n.length&&p>=0&&(k=n.eq(p).find("tr").index(r),m=q.normalized[k],l=o.index(),j=f(c,g,l),m[l]=j,m[c.columns].$row=r,"numeric"===(c.parsers[l].type||"").toLowerCase()&&(q.colMax[l]=Math.max(Math.abs(j)||0,q.colMax[l]||0)),j="undefined"!==h?h:c.resort,j!==!1?t(c,j,i):(a.isFunction(i)&&i(b),c.$table.trigger("updateComplete",c.table)))}).bind("addRows"+c.namespace,function(e,h,i,j){if(e.stopPropagation(),b.isUpdating=!0,d(c.cache))m(b),l(b,i,j);else{h=a(h).attr("role","row");var k,n,o,p,q,r=h.filter("tr").length,s=c.$tbodies.index(h.parents("tbody").filter(":first"));for(c.parsers&&c.parsers.length||g(b),k=0;r>k;k++){for(o=h[k].cells.length,q=[],p={child:[],$row:h.eq(k),order:c.cache[s].normalized.length},n=0;o>n;n++)q[n]=f(c,h[k].cells[n],n),"numeric"===(c.parsers[n].type||"").toLowerCase()&&(c.cache[s].colMax[n]=Math.max(Math.abs(q[n])||0,c.cache[s].colMax[n]||0));q.push(p),c.cache[s].normalized.push(q)}t(c,i,j)}}).bind("updateComplete"+c.namespace,function(){b.isUpdating=!1}).bind("sorton"+c.namespace,function(c,f,g,j){var k=b.config;c.stopPropagation(),e.trigger("sortStart",this),o(b,f),n(b),k.delayInit&&d(k.cache)&&h(b),e.trigger("sortBegin",this),r(b),i(b,j),e.trigger("sortEnd",this),v.applyWidget(b),a.isFunction(g)&&g(b)}).bind("appendCache"+c.namespace,function(c,d,e){c.stopPropagation(),i(b,e),a.isFunction(d)&&d(b)}).bind("updateCache"+c.namespace,function(d,e){c.parsers&&c.parsers.length||g(b),h(b),a.isFunction(e)&&e(b)}).bind("applyWidgetId"+c.namespace,function(a,d){a.stopPropagation(),v.getWidgetById(d).format(b,c,c.widgetOptions)}).bind("applyWidgets"+c.namespace,function(a,c){a.stopPropagation(),v.applyWidget(b,c)}).bind("refreshWidgets"+c.namespace,function(a,c,d){a.stopPropagation(),v.refreshWidgets(b,c,d)}).bind("destroy"+c.namespace,function(a,c,d){a.stopPropagation(),v.destroy(b,c,d)}).bind("resetToLoadState"+c.namespace,function(){v.removeWidget(b,!0,!1),c=a.extend(!0,v.defaults,c.originalSettings),b.hasInitialized=!1,v.setup(b,c)})}var v=this;v.version="2.22.1",v.parsers=[],v.widgets=[],v.defaults={theme:"default",widthFixed:!1,showProcessing:!1,headerTemplate:"{content}",onRenderTemplate:null,onRenderHeader:null,cancelSelection:!0,tabIndex:!0,dateFormat:"mmddyyyy",sortMultiSortKey:"shiftKey",sortResetKey:"ctrlKey",usNumberFormat:!0,delayInit:!1,serverSideSorting:!1,resort:!0,headers:{},ignoreCase:!0,sortForce:null,sortList:[],sortAppend:null,sortStable:!1,sortInitialOrder:"asc",sortLocaleCompare:!1,sortReset:!1,sortRestart:!1,emptyTo:"bottom",stringTo:"max",textExtraction:"basic",textAttribute:"data-text",textSorter:null,numberSorter:null,widgets:[],widgetOptions:{zebra:["even","odd"]},initWidgets:!0,widgetClass:"widget-{name}",initialized:null,tableClass:"",cssAsc:"",cssDesc:"",cssNone:"",cssHeader:"",cssHeaderRow:"",cssProcessing:"",cssChildRow:"tablesorter-childRow",cssIcon:"tablesorter-icon",cssIconNone:"",cssIconAsc:"",cssIconDesc:"",cssInfoBlock:"tablesorter-infoOnly",cssNoSort:"tablesorter-noSort",cssIgnoreRow:"tablesorter-ignoreRow",pointerClick:"click",pointerDown:"mousedown",pointerUp:"mouseup",selectorHeaders:"> thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]},v.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",colgroup:"tablesorter-colgroup",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"},v.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"},v.instanceMethods={},v.log=b,v.benchmark=c,v.getElementText=function(b,c,d){if(!c)return"";var e,f=b.textExtraction||"",g=c.jquery?c:a(c);return"string"==typeof f?a.trim(("basic"===f?g.attr(b.textAttribute)||c.textContent:c.textContent)||g.text()):"function"==typeof f?a.trim(f(g[0],b.table,d)):"function"==typeof(e=v.getColumnData(b.table,f,d))?a.trim(e(g[0],b.table,d)):a.trim(g[0].textContent||g.text())},v.construct=function(b){return this.each(function(){var c=this,d=a.extend(!0,{},v.defaults,b,v.instanceMethods);d.originalSettings=b,!c.hasInitialized&&v.buildTable&&"TABLE"!==this.nodeName?v.buildTable(c,d):v.setup(c,d)})},v.setup=function(c,d){if(!c||!c.tHead||0===c.tBodies.length||c.hasInitialized===!0)return d.debug?b("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"):"";var e="",f=a(c),i=a.metadata;c.hasInitialized=!1,c.isProcessing=!0,c.config=d,a.data(c,"tablesorter",d),d.debug&&a.data(c,"startoveralltimer",new Date),d.supportsDataObject=function(a){return a[0]=parseInt(a[0],10),a[0]>1||1===a[0]&&parseInt(a[1],10)>=4}(a.fn.jquery.split(".")),d.string={max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,"null":0,top:!0,bottom:!1},d.emptyTo=d.emptyTo.toLowerCase(),d.stringTo=d.stringTo.toLowerCase(),/tablesorter\-/.test(f.attr("class"))||(e=""!==d.theme?" tablesorter-"+d.theme:""),d.table=c,d.$table=f.addClass(v.css.table+" "+d.tableClass+e).attr("role","grid"),d.$headers=f.find(d.selectorHeaders),d.namespace?d.namespace="."+d.namespace.replace(/\W/g,""):d.namespace=".tablesorter"+Math.random().toString(16).slice(2),d.$table.children().children("tr").attr("role","row"),d.$tbodies=f.children("tbody:not(."+d.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"}),d.$table.children("caption").length&&(e=d.$table.children("caption")[0],e.id||(e.id=d.namespace.slice(1)+"caption"),d.$table.attr("aria-labelledby",e.id)),d.widgetInit={},d.textExtraction=d.$table.attr("data-text-extraction")||d.textExtraction||"basic",k(c),v.fixColumnWidth(c),v.applyWidgetOptions(c,d),g(c),d.totalRows=0,d.delayInit||h(c),v.bindEvents(c,d.$headers,!0),u(c),d.supportsDataObject&&"undefined"!=typeof f.data().sortlist?d.sortList=f.data().sortlist:i&&f.metadata()&&f.metadata().sortlist&&(d.sortList=f.metadata().sortlist),v.applyWidget(c,!0),d.sortList.length>0?f.trigger("sorton",[d.sortList,{},!d.initWidgets,!0]):(n(c),d.initWidgets&&v.applyWidget(c,!1)),d.showProcessing&&f.unbind("sortBegin"+d.namespace+" sortEnd"+d.namespace).bind("sortBegin"+d.namespace+" sortEnd"+d.namespace,function(a){clearTimeout(d.processTimer),v.isProcessing(c),"sortBegin"===a.type&&(d.processTimer=setTimeout(function(){v.isProcessing(c,!0)},500))}),c.hasInitialized=!0,c.isProcessing=!1,d.debug&&v.benchmark("Overall initialization time",a.data(c,"startoveralltimer")),f.trigger("tablesorter-initialized",c),"function"==typeof d.initialized&&d.initialized(c)},v.fixColumnWidth=function(b){b=a(b)[0];var c,d,e,f,g,h=b.config,i=h.$table.children("colgroup");if(i.length&&i.hasClass(v.css.colgroup)&&i.remove(),h.widthFixed&&0===h.$table.children("colgroup").length){for(i=a(''),c=h.$table.width(),e=h.$tbodies.find("tr:first").children(":visible"),f=e.length,g=0;f>g;g++)d=parseInt(e.eq(g).width()/c*1e3,10)/10+"%",i.append(a("").css("width",d));h.$table.prepend(i)}},v.getColumnData=function(b,c,d,e,f){if("undefined"!=typeof c&&null!==c){b=a(b)[0];var g,h,i=b.config,j=f||i.$headers,k=i.$headerIndexed&&i.$headerIndexed[d]||j.filter('[data-column="'+d+'"]:last');if(c[d])return e?c[d]:c[j.index(k)];for(h in c)if("string"==typeof h&&(g=k.filter(h).add(k.find(h)),g.length))return c[h]}},v.computeColumnIndex=function(b){var c,d,e,f,g,h,i,j,k,l,m,n,o=[],p=[],q={};for(c=0;ce;e++)for("undefined"==typeof o[e]&&(o[e]=[]),p=o[e],f=n;n+m>f;f++)p[f]="x"}return p.length},v.isProcessing=function(b,c,d){b=a(b);var e=b[0].config,f=d||b.find("."+v.css.header);c?("undefined"!=typeof d&&e.sortList.length>0&&(f=f.filter(function(){return this.sortDisabled?!1:v.isValueInArray(parseFloat(a(this).attr("data-column")),e.sortList)>=0})),b.add(f).addClass(v.css.processing+" "+e.cssProcessing)):b.add(f).removeClass(v.css.processing+" "+e.cssProcessing)},v.processTbody=function(b,c,d){b=a(b)[0];var e;return d?(b.isProcessing=!0,c.before(''),e=a.fn.detach?c.detach():c.remove()):(e=a(b).find("span.tablesorter-savemyplace"),c.insertAfter(e),e.remove(),void(b.isProcessing=!1))},v.clearTableBody=function(b){a(b)[0].config.$tbodies.children().detach()},v.bindEvents=function(b,c,e){b=a(b)[0];var f,g=null,i=b.config;e!==!0&&(c.addClass(i.namespace.slice(1)+"_extra_headers"),f=a.fn.closest?c.closest("table")[0]:c.parents("table")[0],f&&"TABLE"===f.nodeName&&f!==b&&a(f).addClass(i.namespace.slice(1)+"_extra_table")),f=(i.pointerDown+" "+i.pointerUp+" "+i.pointerClick+" sort keyup ").replace(/\s+/g," ").split(" ").join(i.namespace+" "),c.find(i.selectorSort).add(c.filter(i.selectorSort)).unbind(f).bind(f,function(e,f){var j,k,l=a(e.target),m=" "+e.type+" ";if(!(1!==(e.which||e.button)&&!m.match(" "+i.pointerClick+" | sort | keyup ")||" keyup "===m&&13!==e.which||m.match(" "+i.pointerClick+" ")&&"undefined"!=typeof e.which||m.match(" "+i.pointerUp+" ")&&g!==e.target&&f!==!0)){if(m.match(" "+i.pointerDown+" "))return g=e.target,k=l.jquery.split("."),void("1"===k[0]&&k[1]<4&&e.preventDefault());if(g=null,/(input|select|button|textarea)/i.test(e.target.nodeName)||l.hasClass(i.cssNoSort)||l.parents("."+i.cssNoSort).length>0||l.parents("button").length>0)return!i.cancelSelection;i.delayInit&&d(i.cache)&&h(b),j=a.fn.closest?a(this).closest("th, td")[0]:/TH|TD/.test(this.nodeName)?this:a(this).parents("th, td")[0],j=i.$headers[c.index(j)],j.sortDisabled||q(b,j,e)}}),i.cancelSelection&&c.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})},v.restoreHeaders=function(b){var c,d,e=a(b)[0].config,f=e.$table.find(e.selectorHeaders),g=f.length;for(c=0;g>c;c++)d=f.eq(c),d.find("."+v.css.headerIn).length&&d.html(e.headerContent[c])},v.destroy=function(b,c,d){if(b=a(b)[0],b.hasInitialized){v.removeWidget(b,!0,!1);var e,f=a(b),g=b.config,h=f.find("thead:first"),i=h.find("tr."+v.css.headerRow).removeClass(v.css.headerRow+" "+g.cssHeaderRow),j=f.find("tfoot:first > tr").children("th, td");c===!1&&a.inArray("uitheme",g.widgets)>=0&&(f.trigger("applyWidgetId",["uitheme"]),f.trigger("applyWidgetId",["zebra"])),h.find("tr").not(i).remove(),e="sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache "+"applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState ".split(" ").join(g.namespace+" "),f.removeData("tablesorter").unbind(e.replace(/\s+/g," ")),g.$headers.add(j).removeClass([v.css.header,g.cssHeader,g.cssAsc,g.cssDesc,v.css.sortAsc,v.css.sortDesc,v.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true"),i.find(g.selectorSort).unbind("mousedown mouseup keypress ".split(" ").join(g.namespace+" ").replace(/\s+/g," ")),v.restoreHeaders(b),f.toggleClass(v.css.table+" "+g.tableClass+" tablesorter-"+g.theme,c===!1),b.hasInitialized=!1,delete b.config.cache,"function"==typeof d&&d(b)}},v.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i},v.sortNatural=function(a,b){if(a===b)return 0;var c,d,e,f,g,h,i,j,k=v.regex;if(k.hex.test(b)){if(d=parseInt(a.match(k.hex),16),f=parseInt(b.match(k.hex),16),f>d)return-1;if(d>f)return 1}for(c=a.replace(k.chunk,"\\0$1\\0").replace(k.chunks,"").split("\\0"),e=b.replace(k.chunk,"\\0$1\\0").replace(k.chunks,"").split("\\0"),j=Math.max(c.length,e.length),i=0;j>i;i++){if(g=isNaN(c[i])?c[i]||0:parseFloat(c[i])||0,h=isNaN(e[i])?e[i]||0:parseFloat(e[i])||0,isNaN(g)!==isNaN(h))return isNaN(g)?1:-1;if(typeof g!=typeof h&&(g+="",h+=""),h>g)return-1;if(g>h)return 1}return 0},v.sortNaturalAsc=function(a,b,c,d,e){if(a===b)return 0;var f=e.string[e.empties[c]||e.emptyTo];return""===a&&0!==f?"boolean"==typeof f?f?-1:1:-f||-1:""===b&&0!==f?"boolean"==typeof f?f?1:-1:f||1:v.sortNatural(a,b)},v.sortNaturalDesc=function(a,b,c,d,e){if(a===b)return 0;var f=e.string[e.empties[c]||e.emptyTo];return""===a&&0!==f?"boolean"==typeof f?f?-1:1:f||1:""===b&&0!==f?"boolean"==typeof f?f?1:-1:-f||-1:v.sortNatural(b,a)},v.sortText=function(a,b){return a>b?1:b>a?-1:0},v.getTextValue=function(a,b,c){if(c){var d,e=a?a.length:0,f=c+b;for(d=0;e>d;d++)f+=a.charCodeAt(d);return b*f}return 0},v.sortNumericAsc=function(a,b,c,d,e,f){if(a===b)return 0;var g=f.config,h=g.string[g.empties[e]||g.emptyTo];return""===a&&0!==h?"boolean"==typeof h?h?-1:1:-h||-1:""===b&&0!==h?"boolean"==typeof h?h?1:-1:h||1:(isNaN(a)&&(a=v.getTextValue(a,c,d)),isNaN(b)&&(b=v.getTextValue(b,c,d)),a-b)},v.sortNumericDesc=function(a,b,c,d,e,f){if(a===b)return 0;var g=f.config,h=g.string[g.empties[e]||g.emptyTo];return""===a&&0!==h?"boolean"==typeof h?h?-1:1:h||1:""===b&&0!==h?"boolean"==typeof h?h?1:-1:-h||-1:(isNaN(a)&&(a=v.getTextValue(a,c,d)),isNaN(b)&&(b=v.getTextValue(b,c,d)),b-a)},v.sortNumeric=function(a,b){return a-b},v.characterEquivalents={a:"áàâãäąå",A:"ÁÀÂÃÄĄÅ",c:"çćč",C:"ÇĆČ",e:"éèêëěę",E:"ÉÈÊËĚĘ",i:"íìİîïı",I:"ÍÌİÎÏ",o:"óòôõöō",O:"ÓÒÔÕÖŌ",ss:"ß",SS:"ẞ",u:"úùûüů",U:"ÚÙÛÜŮ"},v.replaceAccents=function(a){var b,c="[",d=v.characterEquivalents;if(!v.characterRegex){v.characterRegexArray={};for(b in d)"string"==typeof b&&(c+=d[b],v.characterRegexArray[b]=new RegExp("["+d[b]+"]","g"));v.characterRegex=new RegExp(c+"]")}if(v.characterRegex.test(a))for(b in d)"string"==typeof b&&(a=a.replace(v.characterRegexArray[b],b));return a},v.isValueInArray=function(a,b){var c,d=b.length;for(c=0;d>c;c++)if(b[c][0]===a)return c;return-1},v.addParser=function(a){var b,c=v.parsers.length,d=!0;for(b=0;c>b;b++)v.parsers[b].id.toLowerCase()===a.id.toLowerCase()&&(d=!1);d&&v.parsers.push(a)},v.addInstanceMethods=function(b){a.extend(v.instanceMethods,b)},v.getParserById=function(a){if("false"==a)return!1;var b,c=v.parsers.length;for(b=0;c>b;b++)if(v.parsers[b].id.toLowerCase()===a.toString().toLowerCase())return v.parsers[b];return!1},v.addWidget=function(a){v.widgets.push(a)},v.hasWidget=function(b,c){return b=a(b),b.length&&b[0].config&&b[0].config.widgetInit[c]||!1},v.getWidgetById=function(a){var b,c,d=v.widgets.length;for(b=0;d>b;b++)if(c=v.widgets[b],c&&c.hasOwnProperty("id")&&c.id.toLowerCase()===a.toLowerCase())return c},v.applyWidgetOptions=function(b,c){var d,e,f=c.widgets.length,g=c.widgetOptions;if(f)for(d=0;f>d;d++)e=v.getWidgetById(c.widgets[d]),e&&"options"in e&&(g=b.config.widgetOptions=a.extend(!0,{},e.options,g))},v.applyWidget=function(b,d,e){b=a(b)[0];var f,g,h,i,j,k,l,m=b.config,n=m.widgetOptions,o=" "+m.table.className+" ",p=[];if(d===!1||!b.hasInitialized||!b.isApplyingWidgets&&!b.isUpdating){if(m.debug&&(i=new Date),l=new RegExp("\\s"+m.widgetClass.replace(/\{name\}/i,"([\\w-]+)")+"\\s","g"),o.match(l)&&(k=o.match(l)))for(g=k.length,f=0;g>f;f++)m.widgets.push(k[f].replace(l,"$1"));if(m.widgets.length){for(b.isApplyingWidgets=!0,m.widgets=a.grep(m.widgets,function(b,c){return a.inArray(b,m.widgets)===c}),h=m.widgets||[],g=h.length,f=0;g>f;f++)l=v.getWidgetById(h[f]),l&&l.id&&(l.priority||(l.priority=10),p[f]=l);for(p.sort(function(a,b){return a.priorityf;f++)p[f]&&((d||!m.widgetInit[p[f].id])&&(m.widgetInit[p[f].id]=!0,b.hasInitialized&&v.applyWidgetOptions(b,m),"init"in p[f]&&(m.debug&&(j=new Date),p[f].init(b,p[f],m,n),m.debug&&v.benchmark("Initializing "+p[f].id+" widget",j))),!d&&"format"in p[f]&&(m.debug&&(j=new Date),p[f].format(b,m,n,!1),m.debug&&v.benchmark((d?"Initializing ":"Applying ")+p[f].id+" widget",j)));d||"function"!=typeof e||e(b)}setTimeout(function(){b.isApplyingWidgets=!1,a.data(b,"lastWidgetApplication",new Date)},0),m.debug&&(k=m.widgets.length,c("Completed "+(d===!0?"initializing ":"applying ")+k+" widget"+(1!==k?"s":""),i))}},v.removeWidget=function(c,d,e){c=a(c)[0];var f,g,h,i,j=c.config;if(d===!0)for(d=[],i=v.widgets.length,h=0;i>h;h++)g=v.widgets[h],g&&g.id&&d.push(g.id);else d=(a.isArray(d)?d.join(","):d||"").toLowerCase().split(/[\s,]+/);for(i=d.length,f=0;i>f;f++)g=v.getWidgetById(d[f]),h=a.inArray(d[f],j.widgets),g&&"remove"in g&&(j.debug&&h>=0&&b('Removing "'+d[f]+'" widget'),g.remove(c,j,j.widgetOptions,e),j.widgetInit[d[f]]=!1),h>=0&&e!==!0&&j.widgets.splice(h,1)},v.refreshWidgets=function(b,c,d){b=a(b)[0];var e,f=b.config,g=f.widgets,h=v.widgets,i=h.length,j=[],k=function(b){a(b).trigger("refreshComplete")};for(e=0;i>e;e++)h[e]&&h[e].id&&(c||a.inArray(h[e].id,g)<0)&&j.push(h[e].id);v.removeWidget(b,j.join(","),!0),d!==!0?(v.applyWidget(b,c||!1,k),c&&v.applyWidget(b,!1,k)):k(b)},v.getColumnText=function(b,c,e){b=a(b)[0];var f,g,h,i,j,k,l,m,n,o,p="function"==typeof e,q="all"===c,r={raw:[],parsed:[],$cell:[]},s=b.config;if(!d(s)){for(j=s.$tbodies.length,f=0;j>f;f++)for(h=s.cache[f].normalized,k=h.length,g=0;k>g;g++)o=!0,i=h[g],m=q?i.slice(0,s.columns):i[c],i=i[s.columns],l=q?i.raw:i.raw[c],n=q?i.$row.children():i.$row.children().eq(c),p&&(o=e({tbodyIndex:f,rowIndex:g,parsed:m,raw:l,$row:i.$row,$cell:n})),o!==!1&&(r.parsed.push(m),r.raw.push(l),r.$cell.push(n));return r}},v.getData=function(b,c,d){var e,f,g="",h=a(b);return h.length?(e=a.metadata?h.metadata():!1,f=" "+(h.attr("class")||""),"undefined"!=typeof h.data(d)||"undefined"!=typeof h.data(d.toLowerCase())?g+=h.data(d)||h.data(d.toLowerCase()):e&&"undefined"!=typeof e[d]?g+=e[d]:c&&"undefined"!=typeof c[d]?g+=c[d]:" "!==f&&f.match(" "+d+"-")&&(g=f.match(new RegExp("\\s"+d+"-([\\w-]+)"))[1]||""),a.trim(g)):""},v.formatFloat=function(b,c){if("string"!=typeof b||""===b)return b;var d,e=c&&c.config?c.config.usNumberFormat!==!1:"undefined"!=typeof c?c:!0;return b=e?b.replace(/,/g,""):b.replace(/[\s|\.]/g,"").replace(/,/g,"."),/^\s*\([.\d]+\)/.test(b)&&(b=b.replace(/^\s*\(([.\d]+)\)/,"-$1")),d=parseFloat(b),isNaN(d)?a.trim(b):d},v.isDigit=function(a){return isNaN(a)?/^[\-+(]?\d+[)]?$/.test(a.toString().replace(/[,.'"\s]/g,"")):""!==a}}});var b=a.tablesorter;a.fn.extend({tablesorter:b.construct}),b.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"}),b.addParser({id:"text",is:function(){return!0},format:function(c,d){var e=d.config;return c&&(c=a.trim(e.ignoreCase?c.toLocaleLowerCase():c),c=e.sortLocaleCompare?b.replaceAccents(c):c),c},type:"text"}),b.addParser({id:"digit",is:function(a){return b.isDigit(a)},format:function(c,d){var e=b.formatFloat((c||"").replace(/[^\w,. \-()]/g,""),d);return c&&"number"==typeof e?e:c?a.trim(c&&d.config.ignoreCase?c.toLocaleLowerCase():c):c},type:"numeric"}),b.addParser({id:"currency",is:function(a){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((a||"").replace(/[+\-,. ]/g,""))},format:function(c,d){var e=b.formatFloat((c||"").replace(/[^\w,. \-()]/g,""),d);return c&&"number"==typeof e?e:c?a.trim(c&&d.config.ignoreCase?c.toLocaleLowerCase():c):c},type:"numeric"}),b.addParser({id:"url",is:function(a){return/^(https?|ftp|file):\/\//.test(a)},format:function(b){return b?a.trim(b.replace(/(https?|ftp|file):\/\//,"")):b},parsed:!0,type:"text"}),b.addParser({id:"isoDate",is:function(a){return/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/.test(a)},format:function(a,b){var c=a?new Date(a.replace(/-/g,"/")):a;return c instanceof Date&&isFinite(c)?c.getTime():a},type:"numeric"}),b.addParser({id:"percent",is:function(a){return/(\d\s*?%|%\s*?\d)/.test(a)&&a.length<15},format:function(a,c){return a?b.formatFloat(a.replace(/%/g,""),c):a},type:"numeric"}),b.addParser({id:"image",is:function(a,b,c,d){return d.find("img").length>0},format:function(b,c,d){return a(d).find("img").attr(c.config.imgAttr||"alt")||b},parsed:!0,type:"text"}),b.addParser({id:"usLongDate",is:function(a){return/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i.test(a)||/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(a)},format:function(a,b){var c=a?new Date(a.replace(/(\S)([AP]M)$/i,"$1 $2")):a; +return c instanceof Date&&isFinite(c)?c.getTime():a},type:"numeric"}),b.addParser({id:"shortDate",is:function(a){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((a||"").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(a,c,d,e){if(a){var f,g,h=c.config,i=h.$headerIndexed[e],j=i.length&&i[0].dateFormat||b.getData(i,b.getColumnData(c,h.headers,e),"dateFormat")||h.dateFormat;return g=a.replace(/\s+/g," ").replace(/[\-.,]/g,"/"),"mmddyyyy"===j?g=g.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$1/$2"):"ddmmyyyy"===j?g=g.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===j&&(g=g.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,"$1/$2/$3")),f=new Date(g),f instanceof Date&&isFinite(f)?f.getTime():a}return a},type:"numeric"}),b.addParser({id:"time",is:function(a){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(a)},format:function(a,b){var c=a?new Date("2000/01/01 "+a.replace(/(\S)([AP]M)$/i,"$1 $2")):a;return c instanceof Date&&isFinite(c)?c.getTime():a},type:"numeric"}),b.addParser({id:"metadata",is:function(){return!1},format:function(b,c,d){var e=c.config,f=e.parserMetadataName?e.parserMetadataName:"sortValue";return a(d).metadata()[f]},type:"numeric"}),b.addWidget({id:"zebra",priority:90,format:function(b,c,d){var e,f,g,h,i,j,k,l,m=new RegExp(c.cssChildRow,"i"),n=c.$tbodies.add(a(c.namespace+"_extra_table").children("tbody:not(."+c.cssInfoBlock+")"));for(c.debug&&(i=new Date),j=0;jk;k++)f=e.eq(k),m.test(f[0].className)||g++,h=g%2===0,f.removeClass(d.zebra[h?1:0]).addClass(d.zebra[h?0:1])},remove:function(a,c,d,e){if(!e){var f,g,h=c.$tbodies,i=(d.zebra||["even","odd"]).join(" ");for(f=0;f'); + filterData(document.getElementById('comment-textarea-' + itemId), tempTextarea); + var comment = tempTextarea.value; + + //comment can't be blank + if (comment == "" || comment == COMMENT_TEXTAREA_TIP_LABEL) { + alert(WARN_COMMENTS_IS_BLANK_LABEL); + return false; + } + + //word count limit + if (COMMENTS_MIN_WORDS_LIMIT != 0) { //removed isCommentsEnabled && --was it worth it? + var value = $("#comment-textarea-" + itemId).val(); + value = value.trim(); + + var wordCount = value ? (value.replace(/['";:,.?\-!]+/g, '').match(/\S+/g) || []).length : 0; + + if(wordCount < COMMENTS_MIN_WORDS_LIMIT){ + alert( WARN_MIN_NUMBER_WORDS_LABEL.replace("{1}", wordCount)); + return false; + } + } + + //add new comment + $.ajax({ + type: "POST", + url: LAMS_URL + 'servlet/rateItem', + data: { + idBox: commentsCriteriaId + '-' + itemId, + comment: comment, + hasRatingLimits: HAS_RATING_LIMITS + }, + success: function(data, textStatus) { + + //add comment to HTML + jQuery('
', { + 'class': "rating-comment", + html: data.comment + }).appendTo('#comments-area-' + itemId); + + //hide comments textarea and button + $("#add-comment-area-" + itemId).hide(); + + //handle rating limits if available + if (HAS_RATING_LIMITS) { + handleRatingLimits(data.countRatedItems); + } + + } + }); + //apply only once + }).removeClass("add-comment-new"); +} + +function handleRatingLimits(countRatedItems) { + + if (HAS_RATING_LIMITS) { + + //update info box + $("#count-rated-items").html(countRatedItems); + + //callback function + if (typeof onRatingSuccessCallback === "function") { + // safe to use the function + onRatingSuccessCallback(countRatedItems); + } + + //handle max rates limit + if (MAX_RATES != 0) { + + //disable rating feature in case MAX_RATES limit reached + if (countRatedItems >= MAX_RATES) { + $(".rating-stars").each(function() { + $(this).unbind().css('cursor','default').addClass('jDisabled'); + }); + } + } + + //handle min rates limit + if (MIN_RATES != 0) { + checkMinimumRatesLimit(countRatedItems) + } + } +} + +function checkMinimumRatesLimit(countRatedItems) { + $( "#learner-submit" ).toggle( countRatedItems >= MIN_RATES ); +} \ No newline at end of file Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/rating/RatingComment.hbm.xml =================================================================== diff -u --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/rating/RatingComment.hbm.xml (revision 0) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/rating/RatingComment.hbm.xml (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/rating/RatingCriteria.hbm.xml =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/rating/RatingCriteria.hbm.xml (.../RatingCriteria.hbm.xml) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/rating/RatingCriteria.hbm.xml (.../RatingCriteria.hbm.xml) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -33,7 +33,23 @@ @hibernate.property column="rating_criteria_type_id" length="11" + + + + @hibernate.class Index: lams_common/src/java/org/lamsfoundation/lams/commonContext.xml =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -232,6 +232,7 @@ + @@ -243,6 +244,8 @@ PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED + PROPAGATION_REQUIRED + PROPAGATION_REQUIRED @@ -447,6 +450,9 @@ + + + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040041.sql =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040041.sql (.../patch02040041.sql) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040041.sql (.../patch02040041.sql) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -14,6 +14,8 @@ rating_criteria_id BIGINT(20) NOT NULL AUTO_INCREMENT , title VARCHAR(255) , rating_criteria_type_id INT(11) NOT NULL DEFAULT 0 + , comments_enabled TINYINT(1) NOT NULL DEFAULT 0 + , comments_min_words_limit INT(11) DEFAULT 0 , order_id INT(11) NOT NULL , tool_content_id BIGINT(20) , item_id BIGINT(20) @@ -45,6 +47,21 @@ REFERENCES lams_user (user_id) ON DELETE CASCADE ON UPDATE CASCADE )ENGINE=InnoDB; +CREATE TABLE lams_rating_comment ( + uid BIGINT(20) NOT NULL AUTO_INCREMENT + , rating_criteria_id BIGINT(20) NOT NULL + , item_id BIGINT(20) + , user_id BIGINT(20) NOT NULL + , comment text + , PRIMARY KEY (uid) + , INDEX (rating_criteria_id) + , CONSTRAINT FK_lams_rating_comment_1 FOREIGN KEY (rating_criteria_id) + REFERENCES lams_rating_criteria (rating_criteria_id) ON DELETE CASCADE ON UPDATE CASCADE + , INDEX (user_id) + , CONSTRAINT FK_lams_rating_comment_2 FOREIGN KEY (user_id) + REFERENCES lams_user (user_id) ON DELETE CASCADE ON UPDATE CASCADE +)ENGINE=InnoDB; + INSERT INTO lams_rating_criteria_type VALUES (1, 'TOOL_ACTIVITY'); INSERT INTO lams_rating_criteria_type VALUES (2, 'AUTHORED_ITEM'); INSERT INTO lams_rating_criteria_type VALUES (3, 'LEARNER_ITEM'); Index: lams_common/src/java/org/lamsfoundation/lams/rating/ToolRatingManager.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/ToolRatingManager.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/ToolRatingManager.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,80 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating; + +import java.util.Collection; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.rating.service.IRatingService; + +/** + * Tool interface that defines the contract regarding Rating and RatingCriteria manipulation. + * + * @author Andrey Balan + */ +public interface ToolRatingManager { + + List getRatingCriterias(Long toolContentId); + + boolean isCommentsEnabled(Long toolContentId); + + /** + * Read modified rating criterias from request, then update existing ones/add new ones/delete removed ones. Used on + * saving content action in authoring. + * + * @param request + * @param oldCriterias + * criterias stored in the DB + * @param toolContentId + */ + void saveRatingCriterias(HttpServletRequest request, Collection oldCriterias, Long toolContentId); + + /** + * Returns results for all items. If result is needed for only one item provide provide it as a single element in a + * itemIds list. + * + * @param contentId + * @param itemIds + * @param isCommentsByOtherUsersRequired + * whether required just comment from the current user or by all users + * results. + * @param userId + * @return + */ + List getRatingCriteriaDtos(Long contentId, Collection itemIds, boolean isCommentsByOtherUsersRequired, Long userId); + + /** + * Returns number of images rated by specified user in a current activity. It counts comments as ratings. + * + * @param toolContentId + * @param userId + * @return + */ + int getCountItemsRatedByUser(Long toolContentId, Integer userId); + +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingCommentDAO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingCommentDAO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingCommentDAO.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,68 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating.dao; + +import java.util.Collection; +import java.util.List; + +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; +import org.lamsfoundation.lams.rating.dto.RatingCommentDTO; +import org.lamsfoundation.lams.rating.model.RatingComment; + +public interface IRatingCommentDAO { + + /** + * Returns list of RatingCommentDTO which hold only minimum information required for displaying in Rating.tag + * Created in order to lighten the data passed from DB. + * + * @param ratingCriteriaId + * @return + */ + List getCommentsByCriteria(Long ratingCriteriaId); + + /** + * Constructs ItemRatingCriteriaDTO for rating criteria that allows comments. + * + * @param ratingCriteriaId + * @param itemId + * @param userId + * @return + */ + List getCommentsByCriteriaAndItem(Long ratingCriteriaId, Long itemId); + + /** + * Constructs ItemRatingCriteriaDTO for rating criteria that allows comments. Returns comments only for itemIds supplied. + * + * @param ratingCriteriaId + * @param itemIds + * @return + */ + List getCommentsByCriteriaAndItems(Long ratingCriteriaId, Collection itemIds); + + List getCommentsByCriteriaAndItemsAndUser(Long ratingCriteriaId, Collection itemIds, + Integer userId); + + RatingComment getComment(Long ratingCriteriaId, Integer userId, Long itemId); + +} Index: lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingCriteriaDAO.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingCriteriaDAO.java (.../IRatingCriteriaDAO.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingCriteriaDAO.java (.../IRatingCriteriaDAO.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -35,6 +35,8 @@ List getByToolContentId(Long toolContentId); - RatingCriteria getByUid(Long ratingCriteriaId); + RatingCriteria getByRatingCriteriaId(Long ratingCriteriaId); + + RatingCriteria getByRatingCriteriaId(Long ratingCriteriaId, Class clasz); } Index: lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingDAO.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingDAO.java (.../IRatingDAO.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dao/IRatingDAO.java (.../IRatingDAO.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -25,27 +25,57 @@ package org.lamsfoundation.lams.rating.dao; -import org.lamsfoundation.lams.rating.dto.RatingDTO; +import java.util.Collection; +import java.util.List; + +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; import org.lamsfoundation.lams.rating.model.Rating; public interface IRatingDAO { - void saveOrUpdate(Rating rating); - + void saveOrUpdate(Object object); + Rating getRating(Long ratingCriteriaId, Integer userId, Long itemId); - - Rating getRating(Long ratingCriteriaId, Integer userId); - + + List getRatingsByUser(Long contentId, Integer userId); + /** * Returns rating statistics by particular item * * @param itemId * @return */ - RatingDTO getRatingAverageDTOByItem(Long ratingCriteriaId, Long itemId); + ItemRatingCriteriaDTO getRatingAverageDTOByItem(Long ratingCriteriaId, Long itemId); - RatingDTO getRatingAverageDTOByUser(Long ratingCriteriaId, Long itemId, Integer userId); + List getRatingAverageByContentAndItem(Long contentId, Long itemId); + + /** + * Returns rating statistics for specified itemIds. + * + * @param contentId + * @param itemIds + * @return + */ + List getRatingAverageByContentAndItems(Long contentId, Collection itemIds); + /** + * Returns rating statistics for entire tool. + * + * @param contentId + * @return + */ + List getRatingAverageByContent(Long contentId); + Rating get(Long uid); + /** + * Returns number of images rated by specified user in a current activity. It counts comments as ratings. This method + * is applicable only for RatingCriterias of LEARNER_ITEM_CRITERIA_TYPE type. + * + * @param toolContentId + * @param userId + * @return + */ + int getCountItemsRatedByUser(final Long toolContentId, final Integer userId); + } Index: lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingCommentDAO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingCommentDAO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingCommentDAO.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,139 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating.dao.hibernate; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; +import org.lamsfoundation.lams.rating.dao.IRatingCommentDAO; +import org.lamsfoundation.lams.rating.dto.RatingCommentDTO; +import org.lamsfoundation.lams.rating.model.Rating; +import org.lamsfoundation.lams.rating.model.RatingComment; + +public class RatingCommentDAO extends LAMSBaseDAO implements IRatingCommentDAO { + private static final String FIND_RATING_BY_CRITERIA_AND_USER_AND_ITEM = "FROM " + RatingComment.class.getName() + + " AS r where r.ratingCriteria.ratingCriteriaId=? AND r.learner.userId=? AND r.itemId=?"; + + private static final String FIND_COMMENTS_BY_CRITERIA_AND_ITEM = "SELECT r.itemId, r.learner.userId, r.comment " + + "FROM " + RatingComment.class.getName() + + " AS r where r.ratingCriteria.ratingCriteriaId=? AND r.itemId=?"; + + private static final String FIND_COMMENTS_BY_CRITERIA_AND_ITEMS = "SELECT r.itemId, r.learner.userId, r.comment " + + "FROM " + RatingComment.class.getName() + + " AS r where r.ratingCriteria.ratingCriteriaId=:ratingCriteriaId AND r.itemId IN (:itemIds)"; + + private static final String FIND_COMMENTS_BY_CRITERIA_AND_ITEMS_AND_USER = "SELECT r.itemId, r.learner.userId, r.comment " + + "FROM " + RatingComment.class.getName() + + " AS r where r.ratingCriteria.ratingCriteriaId=:ratingCriteriaId AND r.itemId IN (:itemIds) AND r.learner.userId=:userId"; + + private static final String FIND_COMMENTS_BY_CRITERIA = "SELECT r.itemId, r.learner.userId, r.comment " + + "FROM " + RatingComment.class.getName() + " AS r where r.ratingCriteria.ratingCriteriaId=?"; + +// private static final String COUNT_COMMENTS_BY_ITEM_AND_USER = "SELECT COUNT(r) FROM " +// + RatingComment.class.getName() +// + " AS r " +// + " WHERE r.ratingCriteria.toolContentId = ? AND r.ratingCriteria.commentsEnabled IS TRUE AND r.itemId =? AND r.learner.userId =?"; + + @Override + public List getCommentsByCriteriaAndItem(Long ratingCriteriaId, Long itemId) { + List results = (List) (doFind(FIND_COMMENTS_BY_CRITERIA_AND_ITEM, new Object[] { + ratingCriteriaId, itemId })); + + return convertIntoCommentDtos(results); + } + + @Override + public List getCommentsByCriteriaAndItems(Long ratingCriteriaId, Collection itemIds) { + + List results = getSession().createQuery(FIND_COMMENTS_BY_CRITERIA_AND_ITEMS) + .setLong("ratingCriteriaId", ratingCriteriaId).setParameterList("itemIds", itemIds).list(); + + return convertIntoCommentDtos(results); + } + + @Override + public List getCommentsByCriteriaAndItemsAndUser(Long ratingCriteriaId, Collection itemIds, + Integer userId) { + + List results = getSession().createQuery(FIND_COMMENTS_BY_CRITERIA_AND_ITEMS_AND_USER) + .setLong("ratingCriteriaId", ratingCriteriaId).setParameterList("itemIds", itemIds) + .setInteger("userId", userId).list(); + + return convertIntoCommentDtos(results); + } + + @Override + public List getCommentsByCriteria(Long ratingCriteriaId) { + List results = (List) (doFind(FIND_COMMENTS_BY_CRITERIA, + new Object[] { ratingCriteriaId })); + + return convertIntoCommentDtos(results); + } + + /* + * Converts DB results presentation into list of RatingCommentDTO. + * + * @param results + * @return + */ + private List convertIntoCommentDtos(List results) { + + //populate RatingCommentDTOs list + List commentDtos = new LinkedList(); + for (Object[] result : results) { + Long itemId = (Long) result[0]; + Long userId = ((Integer) result[1]).longValue(); + String comment = (String) result[2]; + + RatingCommentDTO commentDto = new RatingCommentDTO(itemId, userId, comment); + commentDtos.add(commentDto); + } + + return commentDtos; + } + + @Override + public RatingComment getComment(Long ratingCriteriaId, Integer userId, Long itemId) { + List list = (List) doFind(FIND_RATING_BY_CRITERIA_AND_USER_AND_ITEM, + new Object[] { ratingCriteriaId, userId, itemId }); + if (list.size() > 0) { + return (RatingComment) list.get(0); + } else { + return null; + } + } + +// @Override +// public boolean isUserCommentedItem(Long toolContentId, Long itemId, Integer userId) { +// List list = getHibernateTemplate().find(COUNT_COMMENTS_BY_ITEM_AND_USER, +// new Object[] { toolContentId, itemId, userId }); +// if (list == null || list.size() == 0) { +// return false; +// } else { +// return ((Number) list.get(0)).intValue() > 0; +// } +// } +} Index: lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingCriteriaDAO.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingCriteriaDAO.java (.../RatingCriteriaDAO.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingCriteriaDAO.java (.../RatingCriteriaDAO.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -27,7 +27,12 @@ import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; import org.lamsfoundation.lams.rating.dao.IRatingCriteriaDAO; +import org.lamsfoundation.lams.rating.model.AuthoredItemRatingCriteria; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; +import org.lamsfoundation.lams.rating.model.LessonRatingCriteria; import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.rating.model.ToolActivityRatingCriteria; +import org.springframework.dao.DataRetrievalFailureException; public class RatingCriteriaDAO extends LAMSBaseDAO implements IRatingCriteriaDAO { @@ -47,15 +52,47 @@ @Override public List getByToolContentId(Long toolContentId) { - return (List) (doFind(FIND_BY_TOOL_CONTENT_ID, new Object[] { toolContentId })); + return (List) (doFind(FIND_BY_TOOL_CONTENT_ID, + new Object[] { toolContentId })); } - public RatingCriteria getByUid(Long ratingCriteriaId) { - if (ratingCriteriaId != null) { - Object o = super.find(RatingCriteria.class, ratingCriteriaId); - return (RatingCriteria) o; - } else { + @Override + public RatingCriteria getByRatingCriteriaId(Long ratingCriteriaId) { + if (ratingCriteriaId == null) { return null; } + + RatingCriteria criteria = (RatingCriteria) super.find(RatingCriteria.class, ratingCriteriaId); + + /** + * we must return the real activity, not a Hibernate proxy. So relook it up. This should be quick as it should + * be in the cache. + */ + if (criteria != null) { + Integer criteriaType = criteria.getRatingCriteriaTypeId(); + if (criteriaType != null) { + switch (criteriaType.intValue()) { + case RatingCriteria.TOOL_ACTIVITY_CRITERIA_TYPE: + return getByRatingCriteriaId(ratingCriteriaId, ToolActivityRatingCriteria.class); + case RatingCriteria.AUTHORED_ITEM_CRITERIA_TYPE: + return getByRatingCriteriaId(ratingCriteriaId, AuthoredItemRatingCriteria.class); + case RatingCriteria.LEARNER_ITEM_CRITERIA_TYPE: + return getByRatingCriteriaId(ratingCriteriaId, LearnerItemRatingCriteria.class); + case RatingCriteria.LESSON_CRITERIA_TYPE: + return getByRatingCriteriaId(ratingCriteriaId, LessonRatingCriteria.class); + default: + break; + } + } + throw new DataRetrievalFailureException( + "Unable to get RatingCriteria as the RatingCriteria type is unknown or missing. RatingCriteria type is " + + criteriaType); + } + return null; } + + @Override + public RatingCriteria getByRatingCriteriaId(Long ratingCriteriaId, Class clasz) { + return (RatingCriteria) super.find(clasz, ratingCriteriaId); + } } Index: lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingDAO.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingDAO.java (.../RatingDAO.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dao/hibernate/RatingDAO.java (.../RatingDAO.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -26,45 +26,75 @@ package org.lamsfoundation.lams.rating.dao.hibernate; import java.text.NumberFormat; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; import org.lamsfoundation.lams.rating.dao.IRatingDAO; -import org.lamsfoundation.lams.rating.dto.RatingDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; import org.lamsfoundation.lams.rating.model.Rating; +import org.lamsfoundation.lams.rating.model.RatingComment; public class RatingDAO extends LAMSBaseDAO implements IRatingDAO { private static final String FIND_RATING_BY_CRITERIA_AND_USER_AND_ITEM = "FROM " + Rating.class.getName() + " AS r where r.ratingCriteria.ratingCriteriaId=? AND r.learner.userId=? AND r.itemId=?"; - private static final String FIND_RATING_VALUE = "SELECT r.rating FROM " + Rating.class.getName() + + private static final String FIND_USER_RATING_VALUE = "SELECT r.rating FROM " + Rating.class.getName() + " AS r where r.ratingCriteria.ratingCriteriaId=? AND r.learner.userId=? AND r.itemId=?"; + private static final String FIND_RATING_BY_CRITERIA_AND_USER = "FROM " + Rating.class.getName() + " AS r where r.ratingCriteria.ratingCriteriaId=? AND r.learner.userId=?"; + + private static final String FIND_RATINGS_BY_USER = "FROM " + Rating.class.getName() + + " AS r where r.ratingCriteria.toolContentId=? AND r.learner.userId=?"; + private static final String FIND_RATING_AVERAGE_BY_ITEM = "SELECT AVG(r.rating), COUNT(*) FROM " + Rating.class.getName() + " AS r where r.ratingCriteria.ratingCriteriaId=? AND r.itemId=?"; + + private static final String FIND_RATING_AVERAGE_BY_CONTENT_AND_ITEM = "SELECT r.itemId, r.ratingCriteria.ratingCriteriaId, AVG(r.rating), COUNT(*) FROM " + + Rating.class.getName() + " AS r where r.ratingCriteria.toolContentId=? AND r.itemId=? GROUP BY r.ratingCriteria.ratingCriteriaId"; + + private static final String FIND_RATING_AVERAGE_BY_CONTENT_AND_ITEMS = "SELECT r.itemId, r.ratingCriteria.ratingCriteriaId, AVG(r.rating), COUNT(*) FROM " + + Rating.class.getName() + + " AS r where r.ratingCriteria.toolContentId=:contentId AND r.itemId IN (:itemIds) GROUP BY r.itemId, r.ratingCriteria.ratingCriteriaId"; + private static final String FIND_RATING_AVERAGE_BY_CONTENT_ID = "SELECT r.itemId, r.ratingCriteria.ratingCriteriaId, AVG(r.rating), COUNT(*) FROM " + + Rating.class.getName() + + " AS r where r.ratingCriteria.toolContentId=? GROUP BY r.itemId, r.ratingCriteria.ratingCriteriaId"; + +// private static final String COUNT_ITEMS_RATED_BY_ACTIVITY_AND_USER = "SELECT COUNT(DISTINCT r.itemId)+(SELECT COUNT(comment) FROM " +// + RatingComment.class.getName() +// + " AS comment " +// + " WHERE comment.ratingCriteria.toolContentId = :toolContentId AND comment.learner.userId =:userId AND comment.itemId =:itemId AND cr.commentsEnabled IS TRUE ) FROM " +// + Rating.class.getName() +// + " AS r " +// + " WHERE r.ratingCriteria.toolContentId = :toolContentId AND r.learner.userId =:userId"; + @Override - public void saveOrUpdate(Rating rating) { - getSession().saveOrUpdate(rating); + public void saveOrUpdate(Object object) { + getSession().saveOrUpdate(object); getSession().flush(); } @Override public Rating getRating(Long ratingCriteriaId, Integer userId, Long itemId) { - List list = (List) doFind(FIND_RATING_BY_CRITERIA_AND_USER_AND_ITEM, new Object[] { ratingCriteriaId, userId, - itemId }); + List list = (List) doFind(FIND_RATING_BY_CRITERIA_AND_USER_AND_ITEM, + new Object[] { ratingCriteriaId, userId, itemId }); if (list.size() > 0) { return (Rating) list.get(0); } else { return null; } } - @Override - public Rating getRating(Long ratingCriteriaId, Integer userId) { - List list = (List) doFind(FIND_RATING_BY_CRITERIA_AND_USER, new Object[] { ratingCriteriaId, userId }); + // method is not used at the moment + private Rating getRating(Long ratingCriteriaId, Integer userId) { + List list = (List) doFind(FIND_RATING_BY_CRITERIA_AND_USER, + new Object[] { ratingCriteriaId, userId }); if (list.size() > 0) { return (Rating) list.get(0); } else { @@ -73,8 +103,14 @@ } @Override - public RatingDTO getRatingAverageDTOByItem(Long ratingCriteriaId, Long itemId) { - List list = (List) doFind(FIND_RATING_AVERAGE_BY_ITEM, new Object[] { ratingCriteriaId, itemId }); + public List getRatingsByUser(Long contentId, Integer userId) { + return (List) doFind(FIND_RATINGS_BY_USER, new Object[] { contentId, userId }); + } + + @Override + public ItemRatingCriteriaDTO getRatingAverageDTOByItem(Long ratingCriteriaId, Long itemId) { + List list = (List) doFind(FIND_RATING_AVERAGE_BY_ITEM, + new Object[] { ratingCriteriaId, itemId }); Object[] results = list.get(0); Object averageRatingObj = (results[0] == null) ? 0 : results[0]; @@ -83,25 +119,27 @@ String averageRating = numberFormat.format(averageRatingObj); String numberOfVotes = (results[1] == null) ? "0" : String.valueOf(results[1]); - return new RatingDTO(averageRating, numberOfVotes); + return new ItemRatingCriteriaDTO(averageRating, numberOfVotes); } @Override - public RatingDTO getRatingAverageDTOByUser(Long ratingCriteriaId, Long itemId, Integer userId) { + public List getRatingAverageByContentAndItem(Long contentId, Long itemId) { + return (List) doFind(FIND_RATING_AVERAGE_BY_CONTENT_AND_ITEM, + new Object[] { contentId, itemId }); + } + + @Override + public List getRatingAverageByContentAndItems(Long contentId, Collection itemIds) { + return getSession().createQuery(FIND_RATING_AVERAGE_BY_CONTENT_AND_ITEMS) + .setLong("contentId", contentId).setParameterList("itemIds", itemIds).list(); + } - RatingDTO ratingDTO = getRatingAverageDTOByItem(ratingCriteriaId, itemId); - - Float userRating = 0F; - List list = doFind(FIND_RATING_VALUE, new Object[] { ratingCriteriaId, userId, itemId }); - if (list.size() > 0) { - userRating = (Float) list.get(0); - } - ratingDTO.setUserRating(userRating.toString()); - ratingDTO.setItemId(itemId); - - return ratingDTO; + @Override + public List getRatingAverageByContent(Long contentId) { + return (List) doFind(FIND_RATING_AVERAGE_BY_CONTENT_ID, new Object[] { contentId }); } + @Override public Rating get(Long uid) { if (uid != null) { Object o = super.find(Rating.class, uid); @@ -110,4 +148,28 @@ return null; } } + + @Override + public int getCountItemsRatedByUser(final Long toolContentId, final Integer userId) { + + // unions don't work in HQL so doing 2 separate DB queries (http://stackoverflow.com/a/3940445) + String FIND_ITEM_IDS_RATED_BY_USER = "SELECT DISTINCT r.itemId FROM " + Rating.class.getName() + " AS r " + + " WHERE r.ratingCriteria.toolContentId = :toolContentId AND r.learner.userId =:userId"; + + String FIND_ITEM_IDS_COMMENTED_BY_USER = "SELECT DISTINCT comment.itemId FROM " + + RatingComment.class.getName() + + " AS comment " + + " WHERE comment.ratingCriteria.toolContentId = :toolContentId AND comment.learner.userId =:userId AND comment.ratingCriteria.commentsEnabled IS TRUE"; + + List ratedItemIds = this.getSession().createQuery(FIND_ITEM_IDS_RATED_BY_USER) + .setLong("toolContentId", toolContentId).setInteger("userId", userId).list(); + + List commentedItemIds = this.getSession().createQuery(FIND_ITEM_IDS_COMMENTED_BY_USER) + .setLong("toolContentId", toolContentId).setInteger("userId", userId).list(); + + Set unionItemIds = new HashSet(ratedItemIds); + unionItemIds.addAll(commentedItemIds); + + return unionItemIds.size(); + } } Index: lams_common/src/java/org/lamsfoundation/lams/rating/dto/ItemRatingCriteriaDTO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/dto/ItemRatingCriteriaDTO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dto/ItemRatingCriteriaDTO.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,78 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating.dto; + +import org.lamsfoundation.lams.rating.model.RatingCriteria; + +public class ItemRatingCriteriaDTO { + + //common properties + private RatingCriteria ratingCriteria; + + //rating properties + private String userRating; + private String averageRating; + private String numberOfVotes; + + public ItemRatingCriteriaDTO() { + } + + public ItemRatingCriteriaDTO(String rating, String numberOfVotes) { + this.averageRating = rating; + this.numberOfVotes = numberOfVotes; + } + + public RatingCriteria getRatingCriteria() { + return ratingCriteria; + } + + public void setRatingCriteria(RatingCriteria ratingCriteria) { + this.ratingCriteria = ratingCriteria; + } + + public String getUserRating() { + return userRating; + } + + public void setUserRating(String userRating) { + this.userRating = userRating; + } + + public String getAverageRating() { + return averageRating; + } + + public void setAverageRating(String averageRating) { + this.averageRating = averageRating; + } + + public String getNumberOfVotes() { + return numberOfVotes; + } + + public void setNumberOfVotes(String numberOfVotes) { + this.numberOfVotes = numberOfVotes; + } + +} Index: lams_common/src/java/org/lamsfoundation/lams/rating/dto/ItemRatingDTO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/dto/ItemRatingDTO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dto/ItemRatingDTO.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,101 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating.dto; + +import java.util.Collection; +import java.util.List; + +public class ItemRatingDTO { + + //common properties + private Long itemId; + private Collection criteriaDtos; + + //comments properties + private boolean commentsEnabled; + private Long commentsCriteriaId; + private int commentsMinWordsLimit; + private List commentDtos; + private RatingCommentDTO commentPostedByUser; + + public ItemRatingDTO () { + commentsEnabled = false; + } + + public Long getItemId() { + return itemId; + } + + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + public Collection getCriteriaDtos() { + return criteriaDtos; + } + + public void setCriteriaDtos(Collection criteriaDtos) { + this.criteriaDtos = criteriaDtos; + } + + public boolean isCommentsEnabled() { + return commentsEnabled; + } + + public void setCommentsEnabled(boolean commentsCriteriaAvailable) { + this.commentsEnabled = commentsCriteriaAvailable; + } + + public Long getCommentsCriteriaId() { + return commentsCriteriaId; + } + + public void setCommentsCriteriaId(Long commentsCriteriaId) { + this.commentsCriteriaId = commentsCriteriaId; + } + + public int getCommentsMinWordsLimit() { + return commentsMinWordsLimit; + } + + public void setCommentsMinWordsLimit(int commentsMinWordsLimit) { + this.commentsMinWordsLimit = commentsMinWordsLimit; + } + + public List getCommentDtos() { + return commentDtos; + } + + public void setCommentDtos(List commentDtos) { + this.commentDtos = commentDtos; + } + + public RatingCommentDTO getCommentPostedByUser() { + return commentPostedByUser; + } + + public void setCommentPostedByUser(RatingCommentDTO commentPostedByUser) { + this.commentPostedByUser = commentPostedByUser; + } +} Index: lams_common/src/java/org/lamsfoundation/lams/rating/dto/RatingCommentDTO.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/dto/RatingCommentDTO.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/dto/RatingCommentDTO.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,76 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating.dto; + + +/** + * Holds minimum information required for displaying in Rating.tag Created in order to lighten the data passed from DB. + * + * @author Andrey Balan + */ +public class RatingCommentDTO { + + private Long itemId; + + private Long userId; + + private String comment; + + public RatingCommentDTO() { + } + + public RatingCommentDTO(Long itemId, Long userId, String comment) { + this.itemId = itemId; + this.userId = userId; + this.comment = comment; + } + + /** + */ + public Long getItemId() { + return itemId; + } + + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + */ + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return this.comment; + } +} Index: lams_common/src/java/org/lamsfoundation/lams/rating/model/RatingComment.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/rating/model/RatingComment.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/rating/model/RatingComment.java (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -0,0 +1,102 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.rating.model; + +import org.lamsfoundation.lams.usermanagement.User; + +/** + */ +public class RatingComment implements java.io.Serializable, Cloneable { + + private static final long serialVersionUID = 4831819420875651676L; + + private Long uid; + + private RatingCriteria ratingCriteria; + + private Long itemId; + + private User learner; + + private String comment; + + public RatingComment() { + } + + public RatingComment(Long itemId, RatingCriteria ratingCriteria, User learner, String comment) { + this.itemId = itemId; + this.ratingCriteria = ratingCriteria; + this.learner = learner; + this.comment = comment; + } + + /** + */ + public Long getUid() { + return uid; + } + + public void setUid(Long uid) { + this.uid = uid; + } + + /** + */ + public Long getItemId() { + return itemId; + } + + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + */ + public RatingCriteria getRatingCriteria() { + return ratingCriteria; + } + + public void setRatingCriteria(RatingCriteria ratingCriteria) { + this.ratingCriteria = ratingCriteria; + } + + /** + */ + public User getLearner() { + return learner; + } + + public void setLearner(User learner) { + this.learner = learner; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return this.comment; + } +} + Index: lams_common/src/java/org/lamsfoundation/lams/rating/model/RatingCriteria.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/model/RatingCriteria.java (.../RatingCriteria.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/model/RatingCriteria.java (.../RatingCriteria.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -82,6 +82,10 @@ /** The type of ratingCriteria */ private Integer ratingCriteriaTypeId; + + private boolean commentsEnabled; + + private int commentsMinWordsLimit; // --------------------------------------------------------------------- // Object constructors @@ -169,7 +173,23 @@ public void setRatingCriteriaTypeId(Integer ratingCriteriaTypeId) { this.ratingCriteriaTypeId = ratingCriteriaTypeId; } + + public boolean isCommentsEnabled() { + return commentsEnabled; + } + public void setCommentsEnabled(boolean commentsEnabled) { + this.commentsEnabled = commentsEnabled; + } + + public int getCommentsMinWordsLimit() { + return commentsMinWordsLimit; + } + + public void setCommentsMinWordsLimit(int commentsMinWordsLimit) { + this.commentsMinWordsLimit = commentsMinWordsLimit; + } + @Override public String toString() { return new ToStringBuilder(this).append("ratingCriteriaId", ratingCriteriaId).toString(); Index: lams_common/src/java/org/lamsfoundation/lams/rating/service/IRatingService.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/service/IRatingService.java (.../IRatingService.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/service/IRatingService.java (.../IRatingService.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -25,45 +25,39 @@ package org.lamsfoundation.lams.rating.service; +import java.util.Collection; import java.util.List; -import org.lamsfoundation.lams.rating.dto.RatingDTO; +import javax.servlet.http.HttpServletRequest; + +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; import org.lamsfoundation.lams.rating.model.Rating; import org.lamsfoundation.lams.rating.model.RatingCriteria; -import org.lamsfoundation.lams.rating.model.ToolActivityRatingCriteria; public interface IRatingService { -// Long createRating(Long id, Integer idType, String signature, Integer userID, String title, String entry); -// -// TreeMap> getEntryByLesson(Integer userID, Integer idType); -// -// List getEntry(Long id, Integer idType, String signature, Integer userID); -// -// List getEntry(Long id, Integer idType, String signature); -// -// List getEntry(Long id, Integer idType, Integer userID); -// -// List getEntry(Integer userID); -// -// List getEntry(Integer userID, Integer idType); -// -// List getEntry(Integer userID, Long lessonID); -// -// Rating getEntry(Long uid); -// -// void updateEntry(Long uid, String title, String entry); -// -// void updateEntry(Rating rating); - void saveOrUpdateRating(Rating rating); - - void saveOrUpdateRatingCriteria(RatingCriteria criteria); - - void deleteRatingCriteria(Long ratingCriteriaId); - + + /** + * Read modified rating criterias from request, then update existing ones/add new ones/delete removed ones. Used on + * saving content action in authoring. + * + * @param request + * @param oldCriterias + * criterias stored in the DB + * @param toolContentId + */ + void saveRatingCriterias(HttpServletRequest request, Collection oldCriterias, Long toolContentId); + List getCriteriasByToolContentId(Long toolContentId); + + RatingCriteria getCriteriaByCriteriaId(Long ratingCriteriaId); + + RatingCriteria getCriteriaByCriteriaId(Long ratingCriteriaId, Class clasz); + boolean isCommentsEnabled(Long toolContentId); + /** * Return Rating by the given itemId and userId. * @@ -80,12 +74,33 @@ * @return */ List getRatingsByItem(Long itemId); - - RatingDTO rateItem(Long ratingCriteriaId, Integer userId, Long itemId, float ratingFloat); - - RatingDTO getRatingDTOByUser(Long ratingCriteriaId, Long itemId, Integer userId); -// IUserManagementService getUserManagementService(); -// -// MessageService getMessageService(); + ItemRatingCriteriaDTO rateItem(RatingCriteria criteria, Integer userId, Long itemId, float ratingFloat); + + void commentItem(RatingCriteria ratingCriteria, Integer userId, Long itemId, String comment); + + /** + * Returns results for all items. If result is needed for only one item provide provide it as a single element in a + * itemIds list. + * + * @param contentId + * @param itemIds + * @param isCommentsByOtherUsersRequired + * whether required just comment from the current user or by all users + * @param userId + * @return + */ + List getRatingCriteriaDtos(Long contentId, Collection itemIds, + boolean isCommentsByOtherUsersRequired, Long userId); + + /** + * Returns number of images rated by specified user in a current activity. It counts comments as ratings. This + * method is applicable only for RatingCriterias of LEARNER_ITEM_CRITERIA_TYPE type. + * + * @param toolContentId + * @param userId + * @return + */ + int getCountItemsRatedByUser(final Long toolContentId, final Integer userId); + } Index: lams_common/src/java/org/lamsfoundation/lams/rating/service/RatingService.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/rating/service/RatingService.java (.../RatingService.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/rating/service/RatingService.java (.../RatingService.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -25,98 +25,47 @@ package org.lamsfoundation.lams.rating.service; +import java.text.NumberFormat; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; +import java.util.Locale; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.lamsfoundation.lams.rating.dao.IRatingCommentDAO; import org.lamsfoundation.lams.rating.dao.IRatingCriteriaDAO; import org.lamsfoundation.lams.rating.dao.IRatingDAO; -import org.lamsfoundation.lams.rating.dto.RatingDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.rating.dto.RatingCommentDTO; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; import org.lamsfoundation.lams.rating.model.Rating; +import org.lamsfoundation.lams.rating.model.RatingComment; import org.lamsfoundation.lams.rating.model.RatingCriteria; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; public class RatingService implements IRatingService { private static Logger log = Logger.getLogger(RatingService.class); private IRatingDAO ratingDAO; - + + private IRatingCommentDAO ratingCommentDAO; + private IRatingCriteriaDAO ratingCriteriaDAO; protected IUserManagementService userManagementService; protected MessageService messageService; -// public TreeMap> getEntryByLesson(Integer userID, Integer idType) { -// TreeMap> entryMap = new TreeMap>(); -// List list = getEntry(userID, idType); -// -// for (Rating entry : list) { -// if (entryMap.containsKey(entry.getItemId())) { -// String lessonName = (String) entryMap.get(entry.getItemId()).get(0).getRating(); -// entry.setRating(lessonName); -// entryMap.get(entry.getItemId()).add(entry); -// } else { -// Lesson lesson = (Lesson) baseDAO.find(Lesson.class, entry.getItemId()); -// List newEntryList = new ArrayList(); -// -// entry.setRating(lesson.getLessonName()); -// newEntryList.add(entry); -// -// entryMap.put(entry.getItemId(), newEntryList); -// } -// } -// -// return entryMap; -// } -// -// public List getEntry(Long id, Integer idType, String signature, Integer userID) { -// return ratingDAO.get(id, idType, signature, userID); -// } -// -// public List getEntry(Long id, Integer idType, String signature) { -// return ratingDAO.get(id, idType, signature); -// } -// -// public List getEntry(Long id, Integer idType, Integer userID) { -// return ratingDAO.get(id, idType, userID); -// } -// -// public List getEntry(Integer userID) { -// return ratingDAO.get(userID); -// } -// -// public List getEntry(Integer userID, Integer idType) { -// return ratingDAO.get(userID, idType); -// } -// -// public List getEntry(Integer userID, Long lessonID) { -// return ratingDAO.get(userID, lessonID); -// } -// -// public Rating getEntry(Long uid) { -// return ratingDAO.get(uid); -// } -// -// public void updateEntry(Long uid, String title, String entry) { -// Rating ne = getEntry(uid); -// if (ne != null) { -// ne.setTitle(title); -// ne.setEntry(entry); -// ne.setLastModified(new Date()); -// saveOrUpdateRating(ne); -// } else { -// log.debug("updateEntry: uid " + uid + "does not exist"); -// } -// } -// -// public void updateEntry(Rating rating) { -// rating.setLastModified(new Date()); -// saveOrUpdateRating(rating); -// } - @Override public Rating getRatingByItemAndUser(Long itemId, Integer userId) { return null; @@ -126,61 +75,298 @@ public List getRatingsByItem(Long itemId) { return null; } - + @Override + public int getCountItemsRatedByUser(final Long toolContentId, final Integer userId) { + return ratingDAO.getCountItemsRatedByUser(toolContentId, userId); + } + + @Override public void saveOrUpdateRating(Rating rating) { ratingDAO.saveOrUpdate(rating); } - + @Override - public RatingDTO rateItem(Long ratingCriteriaId, Integer userId, Long itemId, float ratingFloat) { + public ItemRatingCriteriaDTO rateItem(RatingCriteria ratingCriteria, Integer userId, Long itemId, float ratingFloat) { + Long ratingCriteriaId = ratingCriteria.getRatingCriteriaId(); Rating rating = ratingDAO.getRating(ratingCriteriaId, userId, itemId); - //persist MessageRating changes in DB + // persist MessageRating changes in DB if (rating == null) { // add rating = new Rating(); rating.setItemId(itemId); - + User learner = (User) userManagementService.findById(User.class, userId); rating.setLearner(learner); - - RatingCriteria ratingCriteria = (RatingCriteria) userManagementService.findById(RatingCriteria.class, ratingCriteriaId); + rating.setRatingCriteria(ratingCriteria); } + rating.setRating(ratingFloat); ratingDAO.saveOrUpdate(rating); - - //to make available new changes be visible on a jsp page + + // to make available new changes be visible on a jsp page return ratingDAO.getRatingAverageDTOByItem(ratingCriteriaId, itemId); } - + @Override - public RatingDTO getRatingDTOByUser(Long ratingCriteriaId, Long itemId, Integer userId) { - return ratingDAO.getRatingAverageDTOByUser(ratingCriteriaId, itemId, userId); + public void commentItem(RatingCriteria ratingCriteria, Integer userId, Long itemId, String comment) { + RatingComment ratingComment = ratingCommentDAO.getComment(ratingCriteria.getRatingCriteriaId(), userId, + itemId); + + // persist MessageRating changes in DB + if (ratingComment == null) { // add + ratingComment = new RatingComment(); + ratingComment.setItemId(itemId); + + User learner = (User) userManagementService.findById(User.class, userId); + ratingComment.setLearner(learner); + + ratingComment.setRatingCriteria(ratingCriteria); + } + + ratingComment.setComment(comment); + ratingDAO.saveOrUpdate(ratingComment); } - + @Override + public List getRatingCriteriaDtos(Long contentId, Collection itemIds, boolean isCommentsByOtherUsersRequired, Long userId) { + + //initial preparations + NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); + numberFormat.setMaximumFractionDigits(1); + List criterias = getCriteriasByToolContentId(contentId); + boolean isSingleItem = itemIds.size() == 1; + Long singleItemId = isSingleItem ? itemIds.iterator().next() : null; + + //initialize itemDtos + List itemDtos = new LinkedList(); + for (Long itemId : itemIds) { + ItemRatingDTO itemDto = new ItemRatingDTO(); + itemDto.setItemId(itemId); + itemDtos.add(itemDto); + } + + //handle comments criteria + for (RatingCriteria criteria : criterias) { + if (criteria.isCommentsEnabled()) { + Long commentCriteriaId = criteria.getRatingCriteriaId(); + + List commentDtos; + if (isSingleItem) { + commentDtos = ratingCommentDAO.getCommentsByCriteriaAndItem(commentCriteriaId, singleItemId); + + //query DB using itemIds + } else if (isCommentsByOtherUsersRequired) { + commentDtos = ratingCommentDAO.getCommentsByCriteriaAndItems(commentCriteriaId, itemIds); + + // get only comments for current user + } else { + commentDtos = ratingCommentDAO.getCommentsByCriteriaAndItemsAndUser(commentCriteriaId, itemIds, + userId.intValue()); + } + + for (ItemRatingDTO itemDto: itemDtos) { + itemDto.setCommentsEnabled(true); + itemDto.setCommentsCriteriaId(commentCriteriaId); + itemDto.setCommentsMinWordsLimit(criteria.getCommentsMinWordsLimit()); + + //assign commentDtos by the appropriate items + List commentDtosPerItem = new LinkedList(); + for (RatingCommentDTO commentDto: commentDtos) { + if (commentDto.getItemId().equals(itemDto.getItemId())) { + commentDtosPerItem.add(commentDto); + + //fill in commentPostedByUser field + if (commentDto.getUserId().equals(userId)) { + itemDto.setCommentPostedByUser(commentDto); + } + } + } + + itemDto.setCommentDtos(commentDtosPerItem); + } + + break; + } + } + + //get all data from DB + List userRatings = ratingDAO.getRatingsByUser(contentId, userId.intValue()); + List itemsStatistics; + if (isSingleItem) { + itemsStatistics = ratingDAO.getRatingAverageByContentAndItem(contentId, singleItemId); + + // query DB using itemIds + } else { + itemsStatistics = ratingDAO.getRatingAverageByContentAndItems(contentId, itemIds); + } + + //handle all criterias except for comments' one + for (ItemRatingDTO itemDto : itemDtos) { + Long itemId = itemDto.getItemId(); + List criteriaDtos = new LinkedList(); + itemDto.setCriteriaDtos(criteriaDtos); + + for (RatingCriteria criteria : criterias) { + Long criteriaId = criteria.getRatingCriteriaId(); + + //comments' criteria are handled earlier, at the beginning of this function + if (criteria.isCommentsEnabled()) { + continue; + } + + ItemRatingCriteriaDTO criteriaDto = new ItemRatingCriteriaDTO(); + criteriaDto.setRatingCriteria(criteria); + + // set user's rating + Rating userRating = null; + for (Rating userRatingIter : userRatings) { + if (userRatingIter.getItemId().equals(itemId) + && userRatingIter.getRatingCriteria().getRatingCriteriaId().equals(criteriaId)) { + userRating = userRatingIter; + } + } + String userRatingStr = userRating == null ? "" : numberFormat.format(userRating.getRating()); + criteriaDto.setUserRating(userRatingStr); + + // check if there is any data returned from DB regarding this item and criteria + Object[] itemStatistics = null; + for (Object[] itemStatisticsIter : itemsStatistics) { + Long itemIdIter = (Long) itemStatisticsIter[0]; + Long ratingCriteriaIdIter = (Long) itemStatisticsIter[1]; + + if (itemIdIter.equals(itemId) && ratingCriteriaIdIter.equals(criteriaId)) { + itemStatistics = itemStatisticsIter; + } + } + + String averageRating = itemStatistics == null ? "0" : numberFormat.format(itemStatistics[2]); + String numberOfVotes = itemStatistics == null ? "0" : String.valueOf(itemStatistics[3]); + criteriaDto.setAverageRating(averageRating); + criteriaDto.setNumberOfVotes(numberOfVotes); + + criteriaDtos.add(criteriaDto); + + } + + } + + return itemDtos; + } + + @Override public List getCriteriasByToolContentId(Long toolContentId) { List criterias = ratingCriteriaDAO.getByToolContentId(toolContentId); return criterias; } - + @Override - public void saveOrUpdateRatingCriteria(RatingCriteria criteria) { - ratingCriteriaDAO.saveOrUpdate(criteria); + public RatingCriteria getCriteriaByCriteriaId(Long ratingCriteriaId) { + return ratingCriteriaDAO.getByRatingCriteriaId(ratingCriteriaId); } + + @Override + public RatingCriteria getCriteriaByCriteriaId(Long ratingCriteriaId, Class clasz) { + return ratingCriteriaDAO.getByRatingCriteriaId(ratingCriteriaId, clasz); + } + + @Override + public void saveRatingCriterias(HttpServletRequest request, Collection oldCriterias, + Long toolContentId) { + // create orderId to RatingCriteria map + Map mapOrderIdToRatingCriteria = new HashMap(); + for (RatingCriteria ratingCriteriaIter : oldCriterias) { + mapOrderIdToRatingCriteria.put(ratingCriteriaIter.getOrderId(), ratingCriteriaIter); + } + + int criteriaMaxOrderId = WebUtil.readIntParam(request, "criteriaMaxOrderId"); + // i is equal to an old orderId + for (int i = 1; i <= criteriaMaxOrderId; i++) { + + String criteriaTitle = WebUtil.readStrParam(request, "criteriaTitle" + i, true); + + RatingCriteria ratingCriteria = mapOrderIdToRatingCriteria.get(i); + if (StringUtils.isNotBlank(criteriaTitle)) { + int newCriteriaOrderId = WebUtil.readIntParam(request, "criteriaOrderId" + i); + + // modify existing one if it exists. add otherwise + if (ratingCriteria == null) { + ratingCriteria = new LearnerItemRatingCriteria(); + ratingCriteria.setRatingCriteriaTypeId(LearnerItemRatingCriteria.LEARNER_ITEM_CRITERIA_TYPE); + ((LearnerItemRatingCriteria) ratingCriteria).setToolContentId(toolContentId); + } + + ratingCriteria.setOrderId(newCriteriaOrderId); + ratingCriteria.setTitle(criteriaTitle); + ratingCriteriaDAO.saveOrUpdate(ratingCriteria); + // !!updatedCriterias.add(ratingCriteria); + + // delete + } else if (ratingCriteria != null) { + ratingCriteriaDAO.deleteRatingCriteria(ratingCriteria.getRatingCriteriaId()); + } + + } + + // ==== handle comments criteria ==== + + boolean isCommentsEnabled = WebUtil.readBooleanParam(request, "isCommentsEnabled", false); + // find comments' responsible RatingCriteria + RatingCriteria commentsResponsibleCriteria = null; + for (RatingCriteria ratingCriteriaIter : oldCriterias) { + if (ratingCriteriaIter.isCommentsEnabled()) { + commentsResponsibleCriteria = ratingCriteriaIter; + break; + } + } + // create commentsRatingCriteria if it's required + if (isCommentsEnabled) { + if (commentsResponsibleCriteria == null) { + commentsResponsibleCriteria = new LearnerItemRatingCriteria(); + commentsResponsibleCriteria + .setRatingCriteriaTypeId(LearnerItemRatingCriteria.LEARNER_ITEM_CRITERIA_TYPE); + ((LearnerItemRatingCriteria) commentsResponsibleCriteria).setToolContentId(toolContentId); + commentsResponsibleCriteria.setOrderId(0); + commentsResponsibleCriteria.setCommentsEnabled(true); + } + + int commentsMinWordsLimit = WebUtil.readIntParam(request, "commentsMinWordsLimit"); + commentsResponsibleCriteria.setCommentsMinWordsLimit(commentsMinWordsLimit); + + ratingCriteriaDAO.saveOrUpdate(commentsResponsibleCriteria); + + // delete commentsRatingCriteria if it's not required + } else { + if (commentsResponsibleCriteria != null) { + ratingCriteriaDAO.deleteRatingCriteria(commentsResponsibleCriteria.getRatingCriteriaId()); + } + } + } @Override - public void deleteRatingCriteria(Long ratingCriteriaId) { - ratingCriteriaDAO.deleteRatingCriteria(ratingCriteriaId); + public boolean isCommentsEnabled(Long toolContentId) { + //TODO implement as new DAO method without getting all criterias + List criterias = ratingCriteriaDAO.getByToolContentId(toolContentId); + + boolean isCommentsEnabled = false; + for (RatingCriteria criteria : criterias) { + isCommentsEnabled |= criteria.isCommentsEnabled(); + } + + return isCommentsEnabled; } /* ********** Used by Spring to "inject" the linked objects ************* */ public void setRatingDAO(IRatingDAO ratingDAO) { this.ratingDAO = ratingDAO; } - + + public void setRatingCommentDAO(IRatingCommentDAO ratingCommentDAO) { + this.ratingCommentDAO = ratingCommentDAO; + } + public void setRatingCriteriaDAO(IRatingCriteriaDAO ratingCriteriaDAO) { this.ratingCriteriaDAO = ratingCriteriaDAO; } Index: lams_common/src/java/org/lamsfoundation/lams/web/util/AttributeNames.java =================================================================== diff -u -rf3be94729c90c7390a6aea11d1886a4b72d96670 -r1c42119baf51e12d0ef19919cb5a266a186d4b7d --- lams_common/src/java/org/lamsfoundation/lams/web/util/AttributeNames.java (.../AttributeNames.java) (revision f3be94729c90c7390a6aea11d1886a4b72d96670) +++ lams_common/src/java/org/lamsfoundation/lams/web/util/AttributeNames.java (.../AttributeNames.java) (revision 1c42119baf51e12d0ef19919cb5a266a186d4b7d) @@ -84,8 +84,12 @@ public static final String ATTR_SESSION_STATUS = "sessionStatus"; public static final String ATTR_ACTIVITY_POSITION = "activityPosition"; public static final String ATTR_LEARNER_CONTENT_FOLDER = "learnerContentFolder"; + public static final String ATTR_RATING_CRITERIAS = "ratingCriterias"; public static final String ATTR_RATINGS = "ratings"; + public static final String ATTR_ITEM_RATING_DTO = "itemRatingDto"; + public static final String ATTR_ITEM_RATING_DTOS = "itemRatingDtos"; + public static final String ATTR_COUNT_RATED_ITEMS = "countRatedItems"; // for Pedagogical Planner public static final String PARAM_COMMAND = "command";