A project that I've been working on-again, off-again for the last year or so is finally about to be put into production. As a result, the people who have interests in the system have started making their requests (demands) for how to tweak the system to meet their needs. None of these requests have been anything unreasonable and I believe it's good practice to change your code to meet the needs of your users instead of trying to change your users to meet the needs of your code.
Because of these last-minute requests, I've had to come up with a couple cool tricks to "extend" the functionality of SharePoint. One fairly simple hack that has a lot of potential is one that will let you attach JavaScript events to the controls on a SharePoint form.
I used this bit of code to attach an onChange() event to a select drop-down that would show or hide a textbox based on the selection that had been made. I know there's a lot going on in these screen caps, but for the moment, just focus on the Status drop-down and the displaying of the Outcome row.
(before)

(after)

var theTRs = document.getElementsByTagName("TR");
var rowTitle = "";
for (var r in theTRs) { // loop through every table row on the page
if (theTRs[r].getElementsByTagName("TD")[0]) {
rowTitle = theTRs[r].getElementsByTagName("TD")[0].innerText || theTRs[r].getElementsByTagName("TD")[0].textContent;
rowTitle = (!rowTitle) ? "" : trim(rowTitle);
}
// START PER/ROW CODE //
if (rowTitle.match(/^Status$/)) {
var cellStatus = theTRs[r].getElementsByTagName("TD")[1]; // the cell holding the select dropdown
/** This is where the magic happens. It's not clean or pretty, but it works. **/
cellStatus.innerHTML = theSel.innerHTML.replace(/\<select /i,"<select onChange='statusChange(this.value)' ");
/** I had trouble working with attachEvent & addEventListener so I did it this way **/
theTRs[r].id = "rowStatus" // it's generally ok to assing IDs to rows in SharePoint, but it's very bad form to assign IDs to form controls
}
else if (rowTitle.match(/^Outcome$/)) {
if (cellStatus.getElementsByTagName("SELECT")[0].value.match(/^Pending$/) {
theTRs[r].style.display = "none"; // hide the outcome row if the status is pending
}
theTRs[r].id = "rowOutcome"; // for show/hiding in the statusChange() function
}
// END OF PER/ROW CODE //
}
function statusChange(x) {
if (x.match(/^Completed$/)) {
document.getElementById("rowOutcome").style.display = "";
} else {
document.getElementById("rowOutcome").style.display = "none";
}
}
function trim(x)
{
x = x.replace(/(^\t)(\t*)/,"").replace(/(\t*)(\t$)/,"") // tabs
.replace(/(^\n)(\n*)/,"").replace(/(\n*)(\n$)/,"") // new lines
.replace(/(^\r)(\r*)/,"").replace(/(\r*)(\r$)/,"") // return characters
.replace(/(^<br>)(<br>*)/,"").replace(/(<br>*)(<br>$)/,"") // html returns
.replace(/(^ )( *)/,"").replace(/( *)( $)/,"") // spaces
.replace(/(^ )( *)/,"").replace(/( *)( $)/,""); // html spaces
return x;
}


10 comments:
Hi,
Nice post.
I am trying to "validate/compare values entered by user in textbox against the one's which are in lookup column".
So when user enters, Jin, Chim in textbox it should compare values in lookup field and alert user if duplicate values are entered.
Any help would be appreciated.
Thanks.
Hi Vaishu,
Sorry for taking so long to reply. For that, I'd recommend using the formWorks code instead of this code.
Once you've added this code to the page, you'll want to make the following modifications to both the "/NewForm.aspx/" and "/DispForm.aspx/" blocks in the runMods() function to suit your needs:
textBoxRowName.ctrl.insEvent("onBlur","checkName(this.value)");
You'll also need to add a function named checkName(input) that looks like this:
function checkName(input) {
if (input==lookupRowName.ctrl.value) {
alert("MATCH!");
} else {
// the fields don't match
}
}
This is how I'd approach the task. Please feel free to email me if you have questions.
-Ben
ben[at]bradleyit.com
Hi,
Thanks for your reply.
I am not exactly sure how to use the Formworks code.
I download the code, but it is not in a proper format to open it.
Looking forward to your reply.
Thanks,
Vaishu
Hi Vaishu,
To use the formWorks code, you'll need to add a "Content Editor Web Part" to the bottom of the form. You can do that by adding "ToolPaneView=2" to the end of the page URL that you want to work on.
-Ben
Hi Ben,
For that, I'd recommend using the formWorks code instead of this code.
Once you've added this code to the page, you'll want to make the following modifications to both the "/NewForm.aspx/" and "/DispForm.aspx/" blocks in the runMods() function to suit your needs:
When you say "use Formworks code inside of this code" what do you mean?
Which is the code for formworks which i have to add to the CEWP page.
I am aware of how to add the cewp to newform.aspx and then add the code to that.
-Thanks.
If you download this link and paste the code on that page into the CEWP, you should be able to add your own custom functions to the controls on the form by adding the following code to the appropriate section in the "runMods()" function:
form['Row Name'].ctrl.insEvent("onClick","myFunction()");
The thing i am not able to look at the code on this download link. When I click on the link it downloads in forworks.download format and does not open up.
So i cannot paste any code into the CEWP.
-Thanks,
The "formWorks.download" file is the code file, just renamed from "formWorks.html". If you open that .download file in a simple text editor, you'll see the formWorks code.
Hi,
Thanks.
I got it to work to alert user if value already exists using onchange event handler.
Now I am looking to do validation of values entered by user.
If user enters "Desai Vaishu" and lookup field contains "Vaishu Desai" it should alert saying value already exists.
If lookup value contains "Desai, Vaishu" and user enters "Desai Vaishu" then also it should alert value exists in lookup.
Thanks.
Hi Vaishu,
I'm afraid I can't be too helpful with how to write that part of your code. The best help I can offer is that you can reference both the Lookup and user input control objects in the formWorks code by the following:
...
form['Lookup Title'].ctrl.childNodes;
...
in psuedo-code, it might look like this:
...
var options = form['Lookup Title'].ctrl.childNodes;
for (var o=0;o<options.length;o++) {
if (form['UserInput'].ctrl.value == options[o].value) {
alert('Name already exists!');
}
}
...
-Ben
Post a Comment