var visibleTableHeight = -1; // Freeze the header of listview. function FreezePane() { var $table = $(".ms-listviewtable").first().data("summary", "<listview name>"); var freezedTRHeight = 25; // Determine the available height for table to render in visible screen. if (visibleTableHeight === -1) { var origWorkspaceHeight = $("#s4-workspace").height(); var origTableHeight = $table.height(); var spaceInWorkspaceWithoutTable = origWorkspaceHeight - origTableHeight; var windowHeight = window.innerHeight; if (windowHeight == undefined) { windowHeight = document.documentElement.clientHeight; } var topPos = $("#s4-workspace").offset().top; var availableHeight = windowHeight - topPos - spaceInWorkspaceWithoutTable - freezedTRHeight; // Set visible height, with minimum of 300 visibleTableHeight = Math.max(availableHeight, 300); } // WRAP TABLE IN SCROLL PANE $("#s4-workspace").css( { 'overflow-y': 'auto' } ); $table.wrap(""); // FROZEN HEADER ROW $(".FreezedLV").wrap("<DIV class='FreezedLVContainer' style='position:relative; margin:0px; height:" + (visibleTableHeight + freezedTRHeight) + "px;'></DIV>"); $("<table id='FreezedTR' class='ms-listviewtable' cellPadding='1' cellSpacing='0'></table>").insertBefore(".FreezedLV"); $("#FreezedTR").width($table.width() + "px"); var $origHeader = $("TR.ms-viewheadertr:first", $table); var $firstRowTable = $("TR.ms-itmhover:first", $table); var $freezeHeader = $origHeader.clone(); // Propagate computed width of columns of origheader to freezeheader $origHeader.children("th").each(function() { var width = $(this).width(); var ownerIndex = $(this).index(); $($freezeHeader.children("th")[ownerIndex]).width(width + "px"); }); var $alignerRow = $firstRowTable.clone(); $alignerRow.css( { 'visibility' : 'hidden' } ); $("#FreezedTR").append($alignerRow); $("#FreezedTR").wrap("<DIV style='HEIGHT: " + freezedTRHeight + "px;'></DIV>"); // Visual "hide" the orig header, make sure it still is rendered as otherwise the alignment of 'body' rows is altered $origHeader.children("th").each(function() { $(this).css( { 'height' : '0px' , 'max-height' : '0px', 'min-height' : '0px' , 'padding-top' : '0px', 'padding-bottom' : '0px' } ); $(this).find("div").css( { 'height' : '0px' , 'max-height' : '0px', 'min-height' : '0px', 'margin-top' : '0px', 'margin-bottom' : '0px' } ); $(this).find("input").css( { 'height' : '0px' , 'max-height' : '0px', 'min-height' : '0px' } ); }); $origHeader.css( { 'max-height' : '1px', 'visibility' : 'hidden' } ); // Delegate eventhandlers from the copied+freezed header to the actual header of the listview. var $inputFH = $freezeHeader.find("input[title='Select or deselect all items']"); $inputFH[0].onclick = null; $inputFH[0].onfocus = null; $table.onmouseover = null; $inputFH.click(function() { $(this).closest(".FreezedLVContainer").find(".FreezedLV .ms-viewheadertr").find("input[title='Select or deselect all items']").trigger('click'); }); $inputFH.focus(function() { $(this).closest(".FreezedLVContainer").find(".FreezedLV .ms-viewheadertr").find("input[title='Select or deselect all items']").trigger('focus'); }); $("#FreezedTR").mouseover(function() { $(this).closest(".FreezedLVContainer").find(".FreezedLV .ms-listviewtable").trigger('mouseover'); }); ExecuteOrDelayUntilScriptLoaded(OverloadPositionCtxImg, "core.js"); Overload__doPostBack(); } // Need to update/overload positioning of 'ECB' icon as SharePoint standard it is relative positioned towards its direct parent; // and due scrolling would become invisible. function OverloadPositionCtxImg() { if ($.prototype.KI_base_PositionCtxImg === undefined) { $.prototype.KI_base_PositionCtxImg = PositionCtxImg; PositionCtxImg = function(c, b, h) { $.prototype.KI_base_PositionCtxImg(c, b, h); var a = c.style; a.top = (c.parentNode.offsetTop + b.clientTop) + "px"; }; } } // Overload MicrosoftAjax UpdatePanel function, to restore FreezePane after navigating to another page in the overview. function Overload_updatePanel() { if (Sys.WebForms.PageRequestManager.prototype.KI_base__updatePanel === undefined) { Sys.WebForms.PageRequestManager.prototype.KI_base__updatePanel = Sys.WebForms.PageRequestManager.prototype._updatePanel; Sys.WebForms.PageRequestManager.prototype._updatePanel = function(updatePanelElement, rendering) { Sys.WebForms.PageRequestManager.prototype.KI_base__updatePanel(updatePanelElement, rendering); if (updatePanelElement === $(".ms-listviewtable").first().data("summary", "<listview name>").closest("div")[0]) { if (("td.ms-addnew").length > 1) $("td.ms-addnew").last().closest("table").hide() FreezePane(); } }; } } function Overload__doPostBack() { if ($.prototype.KI_base__doPostBack === undefined) { $.prototype.KI_base__doPostBack = __doPostBack; __doPostBack = function (eventTarget, eventArgument) { // Make sure to overload the updatePanel function before postback from navigate button. if ($.prototype.KI_base__updatePanel === undefined) Overload_updatePanel(); $.prototype.KI_base__doPostBack(eventTarget, eventArgument); } } }
Friday, December 9, 2016
Freeze pane on SharePoint list with responsive scroll height
Sunday, November 27, 2016
Large time-taken value in IISlogs do not per se mean an issue on IIS / SharePoint server level
LogParser.exe "SELECT TOP 10 date,time,c-ip,cs-uri-stem,sc-status,sc-substatus,time-taken from u_ex*.log WHERE time-taken > 2500000 ORDER BY time-taken DESC"
Wednesday, November 16, 2016
Recipe to duplicate InfoPath ListForm template for another content type
- Crafted a rather rich and extensive InfoPath ListForm for content type <X>
- Business requests similar but slightly different form for content type <Y>
- InfoPath Designer does not provide a native capability to duplicate an InfoPath form to another content type
- Drag-and-Drop from source InfoPath form template opened in InfoPath Designer to destination form template is limited, incomplete layout, no controls binding, ...
- Navigate to SharePoint List in a browser
- Go to 'List settings' \ 'Form Settings'
- Select content type <X>, the associated form opens in InfoPath Designer
- Save the template.xsn on a local location (or 'Save as' of the "source files")
- Return to 'List settings' \ 'Form Settings'
- Select content type <Y>, and select to create new form in InfoPath
- Immediate save as template.xsn on a local location, but make sure not to overwrite the one of <X>
- Navigate in Windows Explorer to the location(s) where you saved the .xsn files
- Rename the .xsn file-extension into .cab
- Extract both template.cab archives to local folders
- Open the folder of template for <Y>, and open template.xsf file in an editor. Lookup 'ContentTypeID' in the file, and copy the value
- Open the folder of template for <X>, and open template.xsf file in an editor. Lookup 'ContentTypeID' in the file, and paste the value copied from <Y>. Save the file.
- Make sure to reassign 'Open with' file association for template.xsf file to InfoPath Designer
- Double click the modified template.xsf file, and click 'Design' to open in InfoPath Designer
- Publish the InfoPath form to SharePoint List
- Step 1-10 as above
- Open the folder of template for <Y>, open in an editor the view.xsl for which you want to reuse layout from the form template of content type <X;>, and delete all content
- Open the folder of template for <X>, open in an editor the view.xsl that you want to reuse, select all file content for copy
- Paste the copied file content in the opened view.xsl of content type <Y>, and save the file
- Repeat this for every view in the form template that you want to duplicate/reuse
- Double click the modified template.xsf file, and click 'Design' to open in InfoPath Designer
- Publish the InfoPath form to SharePoint List
Thursday, October 13, 2016
Web-distribution of plain-old HTML/JS/CSS solution in Office 365
Default, custom script is not allowed in Office 365 tenant.
You'll notice the effect of this when you try to add custom script in a ScriptEditor, or on using PageViewer webpart which refuses to remember the url to the (mini)application html file - (Office 365 SharePoint Online - Page Viewer Web Part Not Working)
The resolution is to set in SharePoint Online Admin settings the allowance for custom script - (Turn scripting capabilities on or off). Be aware that it can take up to 24 hours before the effect of the change is actually applied in your Office 365 tenant.
ContentEditor prohibits 'FORM'tags in content:
The resolution is to indeed use a PageViewer webpart, that is if the HTML contains a FORM tag. If not, good old CEWP accept the HTML as included content.
SharePoint Online only supports download action on .htm(l) file
The Microsoft SharePoint team made an explicit design decision to only allow download of html files, and no rendering in browser - (Office 365 - Open html document in browser in document library).
The simple resolution is to change the extension of the .htm(l) files into .axpx, then SharePoint (Online) will no longer include the "X-Download-Options: noopen" header in the HTTP response, and the file is opened in the browser rendering the html code.
Friday, October 7, 2016
On-the-fly extend ECB-menu
var EnrichListView = window.EnrichListView || {}; EnrichListView.UI = function () { function MyCustomItemAction(itemId) { // do something with the item identified by 'itemId' } function OverloadMenuHtc_show() { $.prototype.base_MenuHtc_show = MenuHtc_show; MenuHtc_show = function(oMaster, oParent, fForceRefresh, fFlipTop, yOffset) { if ($(oMaster).find("SPAN[id='ID_EditItem']").length == 1) { var itemId = oParent.childNodes[0].id; var spanInsert = $("<SPAN text='Custom Action on item' onMenuClick='EnrichListView.UI.MyCustomItemAction(" + itemId + ")' type='option' iconAltText sequence='200' CUICommand='CustomActionItems' ></SPAN>"); $(oMaster).append(spanInsert); } $.prototype.base_MenuHtc_show( oMaster, oParent, fForceRefresh, fFlipTop, yOffset); return false; }; } var ModuleInit = (function() { ExecuteOrDelayUntilScriptLoaded(OverloadMenuHtc_show, "core.js"); })(); // Public interface return { MyCustomItemAction: MyCustomItemAction } }();

Tuesday, October 4, 2016
Automatic revert-to-self for InfoPath forms
var InfoPathCheck; var maxNrChecks = 10; $(document).ready(function(){ InfoPathCheck = setInterval(function() { //Wait for InfoPath to finish loading HasInfoPathLoaded(); }, 200); }); function HasInfoPathLoaded() { var selectAppl = $("#<form-id>"); if (selectAppl.length > 0 || --maxNrChecks === 0) { clearInterval(InfoPathCheck); if (selectAppl.length > 0) { var saveBtns = $("input[id^='<form-id>_FormControl'][value^='Save']"); if (saveBtns.length > 0) { $(saveBtns).click(function() { // Overload IP-function to return-to-self upon 'Save'. CurrentFormData_UrlToNavigateToOnClose = function(a) { return document.location.toString(); } }); } } } }
Friday, September 30, 2016
Hide columns from (grouped) ListView with conditional formatting
- CSS:/* * Below CSS-selector is supported in >= IE9, Chrome, FF; but not supported in IE8 */ .ms-listviewtable th:nth-child(3), … .ms-listviewtable td:nth-child(3), … { display:none; } /* * This to compensate with non-support of nth-child in IE8 (compatibility mode) */ .ms-listviewtable th.Hide, .ms-listviewtable td.Hide { display:none; }
- JavaScript:function HideRawDataColumns() { $(‘.ms-listviewtable th:nth-child(3)’).addClass(‘Hide’); $(‘.ms-listviewtable td:nth-child(3)’).addClass(‘Hide’); …. } $(document).ready(function () { HideRawDataColumns (); });
- CSS:/* * Below CSS-selector is supported in >= IE9, Chrome, FF; but not supported in IE8 */ .ms-listviewtable th:nth-child(3), … .ms-listviewtable td:nth-child(3), .. .ms-listviewtable tbody:not([groupString]) td:nth-child(3), … { display:none; } /* * This to compensate with non-support of nth-child in IE8 (compatibility mode) */ .ms-listviewtable th.Hide, .ms-listviewtable td.Hide { display:none; }
- JavaScript:var HideFormatColumnsListView = window.HideFormatColumnsListView || {}; HideFormatColumnsListView.UI = function () { function HideRawDataColumns() { $(‘.ms-listviewtable th:nth-child(3)’).addClass(‘Hide’); $(‘.ms-listviewtable td:nth-child(3)’).addClass(‘Hide’); …. if ($.prototype.base_UpdateCtxLastSelectableRow === undefined) { $.prototype.base_UpdateCtxLastSelectableRow = UpdateCtxLastSelectableRow ; UpdateCtxLastSelectableRow = function(clvpCtx, clvpTab) { $.prototype.base_UpdateCtxLastSelectableRow(clvpCtx, clvpTab); var groupRow = clvpCtx.clvp.tBody; if (groupRow !== null && groupRow !== undefined) { $('td:nth-child(3)', $(groupRow)).addClass('Hide'); … } }; } } var ModuleInit = (function() { ExecuteOrDelayUntilScriptLoaded(function () { HideRawDataColumns() }, "inplview.js"); })(); }();
