MOSS 2007: Adding Filter to ListView web part - sharepoint

I have been dropped into a sharepoint 2007 project, and i have relatively little experience with altering existing webparts.
My first task is to add a filter to two out of three columns in a list view. My Lead Dev suggests trying to add a jquery combo-box filter, and another dev suggests extending the web part and overriding some of the functionality.
What i think is a good option is to change the context menu for the list view headers, so that instead of "Show Filter Choices" bringing up a standard dropdownlist that only responds to the first letter, it would have a jquery combobox. And maybe if the business requests it, change the wording of that option.
My question to you is, what would be a good path to take on this? Also, what resources are there besides traipsing around books and blogs are there to guide an sp newbie to do this?
Thanks.

How about something like this:
<script src="http://www.google.com/jsapi"></script>
<script>
google.load("jquery", "1.2.6");
google.setOnLoadCallback(function() {
$(document).ready(function()
{
jQuery.extend(jQuery.expr[':'], {
containsIgnoreCase: "(a.textContent||a.innerText||jQuery(a).text()||'').toLowerCase().indexOf((m[3]||'').toLowerCase())>=0"
});
$("table.ms-listviewtable tr.ms-viewheadertr").each(function()
{
if($("td.ms-vh-group", this).size() > 0)
{
return;
}
var tdset = "";
var colIndex = 0;
$(this).children("th,td").each(function()
{
if($(this).hasClass("ms-vh-icon"))
{
// attachment
tdset += "<td></td>";
}
else
{
// filterable
tdset += "<td><input type='text' class='vossers-filterfield' filtercolindex='" + colIndex + "' /></td>";
}
colIndex++;
});
var tr = "<tr class='vossers-filterrow'>" + tdset + "</tr>";
$(tr).insertAfter(this);
});
$("input.vossers-filterfield")
.css("border", "1px solid #7f9db9")
.css("width", "100%")
.css("margin", "2px")
.css("padding", "2px")
.keyup(function()
{
var inputClosure = this;
if(window.VossersFilterTimeoutHandle)
{
clearTimeout(window.VossersFilterTimeoutHandle);
}
window.VossersFilterTimeoutHandle = setTimeout(function()
{
var filterValues = new Array();
$("input.vossers-filterfield", $(inputClosure).parents("tr:first")).each(function()
{
if($(this).val() != "")
{
filterValues[$(this).attr("filtercolindex")] = $(this).val();
}
});
$(inputClosure).parents("tr.vossers-filterrow").nextAll("tr").each(function()
{
var mismatch = false;
$(this).children("td").each(function(colIndex)
{
if(mismatch) return;
if(filterValues[colIndex])
{
var val = filterValues[colIndex];
// replace double quote character with 2 instances of itself
val = val.replace(/"/g, String.fromCharCode(34) + String.fromCharCode(34));
if($(this).is(":not(:containsIgnoreCase('" + val + "'))"))
{
mismatch = true;
}
}
});
if(mismatch)
{
$(this).hide();
}
else
{
$(this).show();
}
});
}, 250);
});
});
});
It will need to be added to the page via a content editor web part.

Related

pasting the elements multiple times in rappid js

I am using joint js and rappid with the angular 8 and I have done most of the tasks but in using keyboard events there seems to be a issue. When I copy an element and pasted it on graph it works fine. But for the next element selected it is pasting that new element multiple times.
Here is my code.
var keyboard = this.keyboard = new joint.ui.Keyboard();
var clipboard = this.clipboard = new joint.ui.Clipboard();
selection.collection.on('reset add remove', this.onSelectionChange.bind(this));
paper.on('element:pointerdown', function(elementView: joint.dia.ElementView,evt: joint.dia.Event) {
clipboard.clear();
keyboard.on({
'ctrl+c': function(evt) {
selection.collection.reset();
//clipboard.clear();
selection.collection.add(elementView.model);
clipboard.copyElements(selection.collection, paper.model);
//console.log(clipboard);
},
'ctrl+v': function(evt) {
//console.log(clipboard);
var pastedCells = clipboard.pasteCells(graph, {
translate: { dx: 20, dy: 20 },
useLocalStorage: true
});
var elements = _.filter(pastedCells, function(cell) {
return cell.isElement();
});
//console.log(elements);
// Make sure pasted elements get selected immediately. This makes the UX better as
// the user can immediately manipulate the pasted elements.
selection.collection.reset(elements);
},
});
});
onSelectionChange() {
const { paper, selection,clipboard } = this;
const { collection } = selection;
//console.log(collection.models.child);
// collection.models.forEach(function(model: joint.dia.Element) { if(!model.collection) { clipboard.clear();}});
paper.removeTools();
joint.ui.Halo.clear(paper);
joint.ui.FreeTransform.clear(paper);
joint.ui.Inspector.close();
if(collection.first() == undefined){
clipboard.clear();
}
if (collection.length === 1) {
var primaryCell = collection.first();
var primaryCellView = paper.requireView(primaryCell);
selection.destroySelectionBox(primaryCell);
this.selectPrimaryCell(primaryCellView);
} else if (collection.length === 2) {
collection.each(function(cell) {
selection.createSelectionBox(cell);
});
}
}
selectPrimaryCell(cellView) {
var cell = cellView.model
if (cell.isElement()) {
this.selectPrimaryElement(cellView);
} else {
this.selectPrimaryLink(cellView);
}
//this.createInspector(cell);
}
selectPrimaryElement(elementView) {
var element = elementView.model;
console.log(element.collection);
new joint.ui.FreeTransform({
cellView: elementView,
allowRotation: false,
preserveAspectRatio: !!element.get('preserveAspectRatio'),
allowOrthogonalResize: element.get('allowOrthogonalResize') !== false
}).render();
}
I have different thing like resetting the clipboard , resetting the selection and resetting the keyboard but nothing seems to be working.

How can I add a search button to this existing accordion search code?

I am using the code by Rick Sibley from the first answer on this post: Search within an accordion
Rick mentions that a search button can be added to run the script onclick, in addition to pressing enter to submit and run the search script. Can any body help me add the search 'button' functionality to this, please?
Thanks so much!
I figured it out! I feel like a genius - though I am obviously very bad at this.
Here's what I added in addition to the keyup event listener:
//Search Accordings; Highlight & Open Matching Areas ON SEARCH BUTTON CLICK
function searchBtn() {
var input, filter, i, acc, panels, txtValue, searchText, searchTitle;
input = document.getElementById("keywordSearch");
filter = input.value.toUpperCase();
acc = document.getElementsByClassName("accordion");
panels = document.getElementsByClassName("panel");
for (i = 0; i < panels.length; i++) {
for (i = 0; i < acc.length; i++) {
searchText = panels[i].textContent || panels[i].innerText;
searchTitle = acc[i].textContent || acc[i].innerText;
if (input.value !== "") {
if (searchText.toUpperCase().indexOf(filter) > -1 || searchTitle.toUpperCase().indexOf(filter) > -1) {
if (!acc[i].classList.contains("active")) {
acc[i].classList.add("active");
}
highlightIndex.apply(filter);
panels[i].style.maxHeight = panels[i].scrollHeight + "px";
panels[i].scrollIntoView({
behavior: 'smooth'
});
} else {
if (acc[i].classList.contains("active")) {
acc[i].classList.remove("active");
}
panels[i].style.maxHeight = null;
}
} else {
highlightIndex.remove();
if (acc[i].classList.contains("active")) {
acc[i].classList.remove("active");
}
panels[i].style.maxHeight = null;
}
}
}
}
With the following button added in html
<button type="submit" id="searchBtn" onclick="searchBtn();">Search</button>

Prevent nested lists in text-editor (froala)

I need to prevent/disable nested lists in text editor implemented in Angular. So far i wrote a hack that undos a nested list when created by the user. But if the user creates a normal list and presses the tab-key the list is shown as nested for a few milliseconds until my hack sets in back to a normal list. I need something like event.preventDefault() or stopPropagation() on tab-event keydown but unfortunately that event is not tracked for some reason. Also the froala settings with tabSpaces: falseis not showing any difference when it comes to nested list...in summary i want is: if the user creates a list and presses the tab-key that nothing happens, not even for a millisecond. Has anyone an idea about that?
Froala’s support told us, there’s no built-in way to suppress nested list creation. They result from TAB key getting hit with the caret on a list item. However we found a way to get around this using MutationObserver
Basically we move the now nested list item to his former sibling and remove the newly created list. Finally we take care of the caret position.
var observer = new MutationObserver(mutationObserverCallback);
observer.observe(editorNode, {
childList: true,
subtree: true
});
var mutationObserverCallback = function (mutationList) {
var setCaret = function (ele) {
if (ele.nextSibling) {
ele = ele.nextSibling;
}
var range = document.createRange();
var sel = window.getSelection();
range.setStart(ele, 0);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
};
var handleAddedListNode = function (listNode) {
if (! listNode.parentNode) {
return;
}
var parentListItem = listNode.parentNode.closest('li');
if (!parentListItem) {
return;
}
var idx = listNode.children.length - 1;
while (idx >= 0) {
var childNode = listNode.children[idx];
if (parentListItem.nextSibling) {
parentListItem.parentNode.insertBefore(childNode, parentListItem.nextSibling);
} else {
parentListItem.parentNode.appendChild(childNode);
}
--idx;
}
setCaret(parentListItem);
listNode.parentNode.removeChild(listNode);
};
mutationList.forEach(function (mutation) {
var addedNodes = mutation.addedNodes;
if (!addedNodes.length) {
return;
}
for (var i = 0; i < addedNodes.length; i++) {
var currentNode = addedNodes[i];
switch (currentNode.nodeName.toLowerCase()) {
case 'ol':
case 'ul':
handleAddedListNode(currentNode);
break;
// more optimizations
}
}
})
};

How to return from link formatter url callback without making a hyperlink

I am using the formatter:"link" url callback to generate a hyperlink for a certain column in my Tabulator table
tabulatorTable.addColumn({
title: "Value",
field: "JSONDoc.Path.To.Property",
formatter: "link",
formatterParams: {
url: getHyperLink,
target: "_blank"
}
});
Then in my callback function:
function getHyperLink(cellComp) {
var cellData = cellComp.getData();
var propValFromJSONSource = cellData.SomeProperty;
if( propValFromJSONSource != 0) {
return "http://hostname/report/showLog.php?prop=" + propValFromJSONSource;
}
else {
// If here, I can't generate a valid link, so I want to not have a hyperlink and just show the data
return ???;
}
}
Is there anything that I can do in the else statement to return from the formatter to instruct Tabulator to not create a hyperlink?
I've tried:
return ""; // This makes the hyperlink go to "<currentURL>"
return null; // This generates a relative hyperlink to "<currentURL>/null"
return undefined; // This generates a relative hyperlink to "<currentURL>/undefined"
I suspect I might not be able to use the link formatter and will need to switch to a custom formatter callback that returns "
I also have the problem of not being able to left-click on the hyperlink (even though it appears correctly down in the status bar); I can only center click or right-click and choose "Open in new tab". I'm not sure if this a bug within Tabulator, or Chrome not understanding it for some reason, but that shall be another SO question...
For now, I'm recommending the use of a custom formatter:
tabulatorTable.addColumn({
title: "Value",
field: "JSONDoc.Path.To.Property",
formatter: getHyperLink,
});
Then have the callback return the html code for a hyperlink or just text:
function getHyperLink(cellComp, formatterParams, onRendered) {
var cellData = cellComp.getData();
var cellValue = cellComp.getValue();
var propValFromJSONSource = cellData.SomeProperty;
if( propValFromJSONSource != 0) {
var hrefString = "http://hostname/report/showLog.php?prop=" + propValFromJSONSource;
return "<a href='" + hrefString + "' target='_blank'>" + cellValue + "</a>";
}
else {
return cellValue;
}
}

Sub Grid Total In Crm

I have a primary Entity (Self-Insurance) and a secondary entity (Compensation). They have a 1:N relationship. So in my main form of Self Insurance I have a sub-grid with the name 'Worker_Compensation' where i am adding up some payroll values.
I have 2 questions. . .
1: The thing I want is that when I add some values in the sub-grid. I need to show a sum of all payrolls in the text below of my main form named as 'TOTAL'.
2: Where should i call this java script(On which event) Onload or Onsave of form ? or else where because I can seems to locate the events on Subgrid.
I am using a java script for this purpose.
enter code here
function setupGridRefresh() {
var targetgrid = document.getElementById("Worker_Compensation");
// If already loaded
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
else {
targetgrid.onreadystatechange = function applyRefreshEvent() {
var targetgrid = document.getElementById("Worker_Compensation");
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
}
}
subGridOnload();
}
function subGridOnload() {
//debugger;
var grid = Xrm.Page.ui.controls.get('Worker_Compensation')._control;
var sum = 0.00;
if (grid.get_innerControl() == null) {
setTimeout(subGridOnload, 1000);
return;
}
else if (grid.get_innerControl()._element.innerText.search("Loading") != -1) {
setTimeout(subGridOnload, 1000);
return;
}
var ids = grid.get_innerControl().get_allRecordIds();
var cellValue;
for (i = 0; i < ids.length; i++) {
if (grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]) != "") {
cellValue = grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]);
cellValue = cellValue.substring(2);
cellValue = parseFloat(cellValue);
sum = sum + cellValue;
}
}
var currentSum = Xrm.Page.getAttribute('new_payrolltotal').getValue();
if (sum > 0 || (currentSum != sum && currentSum != null)) {
Xrm.Page.getAttribute('new_payrolltotal').setValue(sum);
}
}
This piece of code is not working. after i add values in the grid my textbox remains empty!
Thanks in advance
If you are upgrading to Microsoft CRM 2015 soon or are already on Microsoft CRM 2015, you can do this without any JavaScript by simply creating a new calculated rollup field and placing that underneath the sub grid, or wherever you wish to place it on the form. Note that this field is calculated ever 12 hours, but if you wish to, it could be calculated on form load via JavaScript. You can see details about that at https://msdn.microsoft.com/en-us/library/dn817863.aspx -"Calculated and Rollup Attributes". The TechNet document, "Define rollup fields" at https://technet.microsoft.com/library/dn832162.aspx has some good examples, scenarios, and discussion about the limitations of the rollup fields.
You can do it with subgrid's onRefresh. This is also unsupportted way but it works. You must add this functions to your javascript
function AddEventToGridRefresh(gridName, functionToCall) {
// retrieve the subgrid
var grid = document.getElementById(gridName);
// if the subgrid still not available we try again after 1 second
if (grid == null) {
setTimeout(function () {AddEventToGridRefresh(gridName, functionToCall);}, 1000);
return;
}
// add the function to the onRefresh event
grid.control.add_onRefresh(functionToCall);
}
// function used in this example
function AdviseUser() {
alert("Sub-Grid refreshed");
}
For more information, here is the link

Resources