Portal is now 8.9 but some customisations from custom.js work while others dont. any ideas?
Our custom.js file has a few customisations, some work and some don’t.
e.g. the ‘adding comment to private” doesn’t work but the custom work item menu badge works customization works. e.g our home page customizations load but gird picker filter doesn't. All were working before the upgrade and are working in our production environment which is on 8.4 version at the moment but are not working correctly in dev (8.9 version). Can we have a look at this? We need it to work, is this an issue with the latest version of the portal, may be some customisations are not compatible with the latest version of the portal? Kind Regards
Answers
Hi Brian,
We have each customization in its separate file with the custom.js just running the getscript functions.
I haven't tried turning them off and re-enabling them. I will give it a shot. im not very good with the dev tools
I will give it a shot.
Thanks for your reply.
thanks Jeff.
I have had a look at the code that we are using for the custo grid picker filter and it doesn't have the "oberser.disconnect"
/*
Customise Grid Control UI to Provide Better Feedback
and
Sort Grid Control Alphabetically.
*/
$(document).ready(function() {
if (document.URL.indexOf("ServiceCatalog/RequestOffering") === -1) { //Only worry about request offering forms
return;
}
//Get all objects that hold our kendo grids.
var divGridControls = $("div[data-control=checkboxGridByCriteriaOld");
for (var i = 0; i < divGridControls.length; i++) {
//Re-get this element as an object.
var thisKendoGrid = $(divGridControls[i]).getKendoGrid();
var kendoGridIndex = i;
thisKendoGrid.kendoGridIndex = kendoGridIndex;
/*Track if Grid is configured for 'Multi-Select'*/
var isMultiSelect = divGridControls[i].getAttribute("data-control-ismultiselect").toLowerCase().trim();
if (isMultiSelect == "true") {
thisKendoGrid.isMultiSelect = true;
}
else {
thisKendoGrid.isMultiSelect = false;
}
/* Keep track of multiple Selected Items in a separate array
This is required as 'thisEventKendoGrid.select()' only returns the last selected item, not all items
Am unsure why this occurs */
if (thisKendoGrid.isMultiSelect) {
thisKendoGrid.selectedItems = new Array();
}
//Add Selection Summary Footer
var selectSummary_html = "<span id='gridSelectSummary" + kendoGridIndex + "' class='gridSelectSummary'></span>";
thisKendoGrid.wrapper.find(".k-pager-info").parent().before(selectSummary_html);
//Pre-set label with 'Empty'
var selectSummary = "<div class='gridSelectSummary-label'>Selection:</div><div class='gridSelectSummary-label'><i><font color=gray>Empty</font></i></div>";
$("#gridSelectSummary" + kendoGridIndex).html(selectSummary);
//Bind 'Change' event whenever a Grid item is selected.
thisKendoGrid.bind("change", function (e){
//Note to self. the dataBound fires after the rows are returned, and dataBinding fires before.
var thisEventKendoGrid = e.sender;
//console.log(e.sender);
/*html layout*/
var selectSummary = "<div class='gridSelectSummary-label'>Selection:</div>";
var entry_html_prefix = "<div class='gridSelectSummary-entity'>";
var entry_html_suffix = "</div>";
var selectedRow = thisEventKendoGrid.select();
var entry_name = thisEventKendoGrid.dataItem(selectedRow).DisplayName;
// Update selectedItems Array with changes
var selectedItems_index = jQuery.inArray(entry_name, thisEventKendoGrid.selectedItems);
if (selectedItems_index == -1) {
//Empty the array if multiSelect is not enabled, as we are changing the selection.
if (thisEventKendoGrid.isMultiSelect == false) {
thisEventKendoGrid.selectedItems = [];
}
//Add new entry.
thisEventKendoGrid.selectedItems.push(entry_name);
}
else {
//Remove entry if re-clicked.
thisEventKendoGrid.selectedItems.splice(selectedItems_index, 1);
}
//Build selected Summary List (using selectedItems Array)
if (thisEventKendoGrid.selectedItems.length == 0) {
selectSummary = selectSummary + "<div class='gridSelectSummary-label'><i><font color=gray>Empty</font></i></div>"
}
else {
if (thisEventKendoGrid.isMultiSelect) {
for (var j = 0; j < thisEventKendoGrid.selectedItems.length; j++) {
selectSummary = selectSummary + entry_html_prefix + " " + thisEventKendoGrid.selectedItems[j] + " " + entry_html_suffix;
}
}
else {
selectSummary = selectSummary + entry_html_prefix + " " + entry_name + " " + entry_html_suffix;
}
}
/*Show selected Summary*/
$("#gridSelectSummary" + thisEventKendoGrid.kendoGridIndex).html(selectSummary);
});
var firstColumnName = thisKendoGrid.columns[0].field;
//var firstColumnTitle = thisKendoGrid.columns[0].title;
var numberOfRows = thisKendoGrid.dataSource.data().length
if (numberOfRows > 0)
{
//This grid control already has data.
//Sort this grid, using the first column. This will sort only once, after initial page load, whether items exist in the grid or not.
thisKendoGrid.dataSource.query({
sort: { field: firstColumnName, dir: "asc" },
page: 1,
pageSize: 8,
});
}
else{
//If this request offering grid uses a previous question filter, then the initial sort won't work. Set up a one-time sort event.
thisKendoGrid.one("dataBound", function (e){
//Note to self. the dataBound fires after the rows are returned, and dataBinding fires before.
var thisEventKendoGrid = e.sender;
console.log(e.sender);
var firstEventColumnName = thisEventKendoGrid.columns[0].field;
var firstEventColumnTitle = thisEventKendoGrid.columns[0].title;
//console.log("Databinding changed in event. Sorting by first column '" + firstEventColumnName + "', '" + firstEventColumnTitle + "'");
thisEventKendoGrid.dataSource.query({
sort: { field: firstEventColumnName, dir: "asc" },
page: 1,
pageSize: 8,
});
});
}
}
});
Neither does the code we are using for comments added as private by Default. any other ideas?
thank for your reply.
Sorry that was the code for the grid picker improvement not the code for the gird picker.
I found the observer.disconnect line and made the change. Cleared my cache, restarted cache builder but no luck.
/* ----------------------------------------------- */
/* -------------- Custom Grid Search ------------- */
/* ----------------------------------------------- */
$(document).ready(function () {
if (session.user.Analyst == 1){
var url = window.location.href;
if(url.indexOf("/View/") == -1 && url.indexOf("/Page/") == -1 )
{
// Loosely verify we are on a page with workitems, not using hte GetProjection API call.
return;
}
var mainPageNode = document.getElementById('main_wrapper');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
if ($("#customgridfilter").length > 0) { //It was already added once from somewhere. Fixes an IE multi-observer bug.
observer.disconnect();
return;
}
//The page changed. See if our title exists. If it does, then our gridview should also exist.
var titleElement = $(".page_title"); //The title "usually" exists. But not on dashboard pages.
var dashboardElement = $(".dashboard"); //The dashboard always exists for...pages with dashboards.
//If this page has a gridview, then it also exists as soon as either the title or dashboard div does.
if (titleElement.length > 0 || dashboardElement.length > 0) { //An element with class of page_title exists.
var gridElement = $('.k-grid-header') // Get the grid object
if (gridElement.length > 0) {
fnAddCustomFilterInputBoxToPage();
//We are done observing.
observer.disconnect();
}
});
// configure the observer and start the instance.
var observerConfig = { attributes: true, childList: true, subtree: true, characterData: true };
observer.observe(mainPageNode, observerConfig);
function fnAddCustomFilterInputBoxToPage() {
var shouldPrependText = false;
var isPromotedView = false; //controls filtering options.
var resetViewButtonParentDiv = $(".btn-clear-grid-filters").first().parent();
if (resetViewButtonParentDiv.length > 0) {
//We shouldn't use this for a promoted view. Only OOB views.
var url = window.location.href;
if (url.indexOf("/c5161e06-2378-4b44-aa89-5600e2d3b9d8") == -1 &&
url.indexOf("/9a06b0af-2910-4783-a857-ba9e0ccb711a") == -1 && url.indexOf("/cca5abda-6803-4833-accd-d59a43e2d2cf") == -1 &&
url.indexOf("/f94d43eb-eb42-4957-8c48-95b9b903c631") == -1 && url.indexOf("/62f452d5-66b5-429b-b2b1-b32d5562092b") == -1
)
{
//console.log("Custom Grid View filter - detected promoted view.");
isPromotedView = true;
}
}
else{
//There was no button with this grid? Try a widget view then.
resetViewButtonParentDiv = $("a:contains('Reset State')").first().parent().parent(); //Add another parent.
shouldPrependText = true;
}
if (resetViewButtonParentDiv.length == 0) {
console.log("Found a grid view, but not a reset button. Cannot show search filter in this scenario.");
return;
}
var strHtmlToAdd = "<div class='customgridsearch' style='margin-left: 10px; margin-top: 10px; display:inline-block;'>" +
"<div style='color:#000; font-family:'400 18px/22px',?'Segoe UI',?'Open Sans',?Helvetica,?sans-serif; display:inline-block; width: 400px;'>" +
"<span>Filter Results: </span>" + "<input type='text' id='customgridfilter' placeholder='Type filter and press enter...' style='color: #000000; width: 200px;' />" +
"</div>" +
"</div>"
console.log("Appending grid view filter");
if (shouldPrependText) {
$(resetViewButtonParentDiv).prepend(strHtmlToAdd);
}
else{
$(resetViewButtonParentDiv).append(strHtmlToAdd);
}
$("#customgridfilter").on('keydown', function(e){
if(e.which == 13) {
//filter our resultset.
var strFilterText = $("#customgridfilter").val().trim();
if (strFilterText.length > 0) {
fnApplyCustomFilterToGridDataSource(strFilterText, isPromotedView);
}
}
else if (e.which == 27) {//escape
$("#customgridfilter").val("");
fnRemoveCustomFiltersOnGridResultSet();
}
});
}
function fnApplyCustomFilterToGridDataSource(strFilterValue, isPromotedView) {
var gridElement = $('[data-role=grid]'); // Get the grid div element
var kendoGridElement = gridElement.data('kendoGrid'); //...as a kendo widget
var datasource = kendoGridElement.dataSource;
var criteriaFilterObjects = []; //empty, for now...
var firstColumn = ""
for(var i = 0; i < kendoGridElement.columns.length; i++) {
//for(var i = 0; i < kendoGridElement.columns.length-10; i++) {
if (kendoGridElement.columns[i].field == "Icon" || kendoGridElement.columns[i].field == "NumericId" ||
kendoGridElement.columns[i].field == "BaseId" || kendoGridElement.columns[i].field == "ParentWorkItemId")
continue;
if (firstColumn == "") {
//Set the first real column, since we need any column to work with for our kendo datasource OR filter later.
firstColumn = kendoGridElement.columns[i].field;
}
if (kendoGridElement.columns[i].DataType == "string" || kendoGridElement.columns[i].DataType == "anchor" ||
(kendoGridElement.columns[i].DataType == undefined && kendoGridElement.columns[i].field.indexOf("Key") == -1)
)
{ //when using a filter, the "contains" operator only works with strings, or else it throws a server 500 error.
//an undefined datatype is a SQL table view from custom SQL source, It still chokes on integers. And we can't guess the type from the column from here?
var newSingleFilterObject = { field: kendoGridElement.columns[i].field, operator: "contains", value: strFilterValue }
criteriaFilterObjects.push(newSingleFilterObject); //add it to our criteriaFilterObjects
}
}
//kendogridview datasources don't allow us to use an OR directly on them. So instead, do an AND, with a nested OR.
//In the case, the first valid column is not null, AND any other column contains the filtered data.
var masterFilter = { logic: "and",
filters: [{
logic:"or",
filters: criteriaFilterObjects
},
{ field : firstColumn, operator : "neq", value: ""} ] //isnotnull doesn't work with this kendo filter?
}
//nestedFilterWithOrColumns = criteriaFilterObjects[2];
//Set our new filter.
if (isPromotedView) {
//In some promoted views, the kendo filter is broken. If column 6 has a null value, then the OR clause removes that entire result, even if another column matches .
//This is bypassed by using client-side filtering.
datasource.options.serverFiltering = false
datasource.options.serverPaging = false
}
datasource.filter(masterFilter);
}
function fnRemoveCustomFiltersOnGridResultSet() {
var gridElement = $('[data-role=grid]'); // Get the grid div element
var kendoGridElement = gridElement.data('kendoGrid'); //...as a kendo widget
var datasource = kendoGridElement.dataSource;
datasource.filter([]);
}
}
});
/* ----------------------------------------------- */
/* ------------ End Custom Grid Search ----------- */
/* ----------------------------------------------- */
below is the code we are using for action log set to private for default.
notice anything that I should change in this?
/* ----------------------------------------------- */
/* --------- IR - Default tick private ----------- */
/* ----------------------------------------------- */
//Change Request Tasks
app.custom.formTasks.add('Incident', null, function(formObj, viewModel){
formObj.boundReady(function () {
//set comments to private by default
$("#actionLogisPrivate").trigger("click").closest("div");
//resets comment to private after adding a comment
pageForm.viewModel.AppliesToTroubleTicket.bind("change", function () {
setTimeout(function () {
$("#actionLogisPrivate").trigger("click").closest("div");
},0);
});
});
});
/* ----------------------------------------------- */
/* ------- END IR - Default tick private --------- */
/* ----------------------------------------------- */
/* ----------------------------------------------- */
/* --------- PR - Default tick private ----------- */
/* ----------------------------------------------- */
//Change Request Tasks
app.custom.formTasks.add('Problem', null, function(formObj, viewModel){
formObj.boundReady(function () {
//set comments to private by default
$("#actionLogisPrivate").trigger("click").closest("div");
//resets comment to private after adding a comment
pageForm.viewModel.AppliesToTroubleTicket.bind("change", function () {
setTimeout(function () {
$("#actionLogisPrivate").trigger("click").closest("div");
},0);
});
});
});
/* ----------------------------------------------- */
/* ------- END PR - Default tick private --------- */
/* ----------------------------------------------- */
/* ----------------------------------------------- */
/* --------- SR - Default tick private ----------- */
/* ----------------------------------------------- */
//Change Request Tasks
app.custom.formTasks.add('ServiceRequest', null, function(formObj, viewModel){
formObj.boundReady(function () {
//set comments to private by default
$("#actionLogisPrivate").trigger("click").closest("div");
//resets comment to private after adding a comment
pageForm.viewModel.AppliesToWorkItem.bind("change", function () {
setTimeout(function () {
$("#actionLogisPrivate").trigger("click").closest("div");
},0);
});
});
});
/* ----------------------------------------------- */
/* ------- END SR - Default tick private --------- */
/* ----------------------------------------------- */
/* ----------------------------------------------- */
/* --------- CR - Default tick private ----------- */
/* ----------------------------------------------- */
//Change Request Tasks
app.custom.formTasks.add('ChangeRequest', null, function(formObj, viewModel){
formObj.boundReady(function () {
//set comments to private by default
$("#actionLogisPrivate").trigger("click").closest("div");
//resets comment to private after adding a comment
pageForm.viewModel.AppliesToWorkItem.bind("change", function () {
setTimeout(function () {
$("#actionLogisPrivate").trigger("click").closest("div");
},0);
});
});
});
/* ----------------------------------------------- */
/* ------- END CR - Default tick private --------- */
/* ----------------------------------------------- */
@jeff_lang
Hi Jeff,
I have tried this, does the below look alright? I'm really bad with coding.
any ideas?
if (titleElement.length > 0 || dashboardElement.length > 0) { //An element with class of page_title exists.
var gridElement = $('.k-grid-header') // Get the grid object
if (gridElement.length > 0) {
fnAddCustomFilterInputBoxToPage();
//We are done observing.
observer.disconnect();
}
}
}
We are also using the colour coded gried view that goes red for high priority jobs. that seems to work for some reason. looking at the code I found the observer.disconnect line.
if (titleElement.length > 0 || dashboardElement.length > 0) { //An element with class of page_title exists.
var gridElement = $('.k-grid-header') // Get the grid object
if (gridElement.length > 0) {
fnAddColorCodedGridView();
}
//We are done observing.
observer.disconnect();
}
});
how ever it seems to work without me touching it. while the same layout in the grid view filter doesn't work.
Hi, we got most of it working as well but not the grid view filter. no matter what I do it doesn't work.
does anyone else have any ideas with this?