SharePoint PeoplePicker - Prevent user deleting value - asp.net

I have a form with a PeoplePicker control on it that I do not want the user to be able to edit.
Normally in situations like these setting the controls Enabled property to false would suffice, however I'm having issues with the value being cleared on postback (the form is very customised with numerous sub-sections that interact with each other).
I've tried the following:
peoplePicker.EnableBrowse = false;
peoplePicker.AllowTypeIn = false;
This solves nearly all my problems, the user cannot enter any values, the value is not cleared on postback, HOWEVER, the user is able to delete the current value.
How can I completely prevent the user from editing the controls value without setting Enabled to false?
Any help is greatly appreciated. Thanks.
EDIT: Forgot to mention this needs to be done server side, there's a lot of logic on the form revolving around the users AD group and their sharepoint permissions so javascript isn't really an option.

SharePoint people picker is basically a div with contenteditable property. If you can inject javascript, here is the solution:
http://www.stuartroberts.net/index.php/2012/03/05/quick-tip-5/

You could prevent users from deleting value by pressing event of Backspace and Delete keys using JavaScript/jQuery solution.
Solution
Along with specifying EnableBrowse and AllowTypeIn properties, add the following script on the page where PeopleEditor control resides:
$("body").on("keydown", "span", function(e) {
if ( (e.keyCode == 8 || e.keyCode == 46) && e.target.id.indexOf("userPicker_upLevelDiv") > -1)
e.preventDefault();
});

Related

Prompt to save data if and when changes have been made

I am using asp.net and I need to display a prompt to the user if they have made changes to the web page, and they accidentally close down the browser.
The page could be anything from "Edit Profile" to a "Submit a Claim" etc.
How can I can display the messagebox, ensuring that it is displayed only if changes have been made (as opposed to, the user making changes, then undo-ing the changes, and shutting down the browser)
What I have done in the past is use some client side scripting which does this check during the onbeforeunload event....
var showPrompt=true;
var isDirty=false;
var hidePopup=false;
function onBeforeUnload() {
if (showPrompt) {
if (isDirty) {
if (hidePopup || confirm("Click ok to save your changes or click cancel to discard your changes.")) {
doSave();
}
}
}
showPrompt = true;
hidePopup = false;
}
ShowPrompt can be set to false when your clicking on an anchor tag which won't navigate you away from the page. For example <a onclick='showPrompt=false' href='javascript:doX()'/>
isDirty can be used to track when you need to save something. You could for example do something like $("input").onchange(function(){isDirty=true;}); To track undo's you might want to replace isDirty with a function which checks the current state from the last saved state.
HidePopup lets us force a save without confirming to the user.
That's very difficult to even touch without understanding what's on the page. If it's a few controls you capture value at page load and store them so you can later compare. If it's a complex page you'd need to do an exact comparison to the entire viewstate.
Typically you'd handle this type of situation by setting a boolean to TRUE the first time any change is made and disregard the user changing it back. If you're just trying to avoid accidential non-save of data the user should be smart enough to know they've "undone" their changes.
You can do this with javascript. See this question and either of the first two answers.

AutoComplete Stopping When User Presses "Enter"

I am using the AutoCompleteExtender on a commercial site. My problem is the users are quickly typing in part of a word and immediately pressing "Enter" which causes the AutoComplete control to NOT come back with a list of suggestions. For example, if my database has the phrase "Texas, United States" in it but the users just type "Texas" quickly followed by Enter then the dropdown list does not appear.
What I would like is for the AutoComplete control to ignore the fact the user has pressed Enter and go and fetch the suggested data anyway. (The ultimate would be if it ignored Enter when there was currently no list, but selected an item when there was a list).
I can simulate this exact problem by going to the samples section of this Microsoft ASP.NET site and typing in some characters very quickly followed by 'Enter'.
Please could someone tell me what I need to do?
Thanks, Martin
I've hacked around this problem before with an extra keydown handler on the textbox that is the target of the auto-complete. Replace this._autoCompleteBehavior in the snippet below with a reference to your instance of AutoCompleteBehavior (obtainable via $find() and the BehaviorID). The idea here is to force the auto-complete behavior to think it needs to perform a lookup by calling _onTimerTick(), which executes after the typing delay has expired. By default the typing delay gets cancelled by hitting the enter key, so this just forces the lookup anyway on enter or tab.
Disclaimer: my hack references "private" members of the AjaxControlToolkit code (stuff that starts with underscore is "private"), so it is probably not guaranteed to be future-proof.
_searchTextbox_keydown: function(e)
{
var key = e.keyCode || e.rawEvent.keyCode;
// If the user hits enter or tab before the auto complete popup appears, force the autocomplete lookup at that moment.
if ((key === Sys.UI.Key.enter || key === Sys.UI.Key.tab) && this._autoCompleteBehavior._currentPrefix != this._autoCompleteBehavior._currentCompletionWord())
{
this._autoCompleteBehavior._onTimerTick(this._autoCompleteBehavior._timer, Sys.EventArgs.Empty);
e.preventDefault();
}
}
Hey try jQuery or YUI autocomplete extender. It will be lightning fast.

Can Anyone Help me with this? Refresh update panel partially onclient side

i have a dynamically created gridview button that fires off a modal popup when clicked. I do this onclientside like so:
function openModal(btnId, v) {
deptdata(v);
// __doPostBack('<%=DropDownList1.ClientID %>', '');
btn = document.getElementById(btnId);
btn.click();
}
function deptdata(v) {
document.getElementById('<%=vendor.ClientID%>').value = v;
}
This is how the function is called in the code.
btnedit.OnClientClick = String.Format("openModal('{0}','" & GridView1.Rows(i).Cells(0).Text & "');return false;", hidden.ClientID)
I set the value of a hidden field(Vendor) but I need that value for what's in the modal popup. I have a dropdown list that depends on that newly set variable. The variable is set depending on what row was clicked. So i need to somehow just reload that popup. I have an Update Panel but I can't get that Panel to reload. I've tried __doPostback and it didn't help. any ideas how to update the panel or the dropdown in the panel using javascript?
It's not very clear from your description and the limited code you provide what it is exactly that you are trying to do and what is failing. However, the following might give you some ideas. If you provide more detail and code someone might be able to give you a better answer.
ScriptManager1.RegisterAsyncPostBackControl(Button1);
to trigger an update panel post back from js make sure you use UniqueID, not ClientID, thats a common gotcha that prevents the async postback from working.
__doPostBack("<%=Button1.UniqueID %>", "");
Personally, I have all but given up on UpdatePanels, I only use them in the most trivial cases. I prefer to have my js call an ASP.Net JSON webservice and have the on completed function render any needed changes to the html. It's more flexible, lighter and infinitely faster for pages with large grids or a lot of controls.

ASP.NET linkbutton raising onBeforeUnload event twice

I've posted this here, but thought it might deserve a question on its own.
What I'm trying to do is show a dialog box that asks the user if he/she wants to leave the page if there are unsaved changes. That all works fine. But the problem is described below:
Has anyone come across the problem where Internet Explorer fires the onbeforeunload event twice? While Googling around, I found it has something to do with the fact that for (among others) an ASP.NET linkbutton the HTML code is <a href="javascript: __doPostBack....
Apparently, when IE encouters a link that doesn't have a href="#", it fires the onbeforeunload event. Then, when you confirm the javascript dialog box we're showing, the page will do the 'real' unload to navigate to the other page, and raise the onbeforeunload event a second time.
A solution offered on the internet is to set a boolean variable and check on it before showing the dialog. So the second time, it wouldn't be shown. That's all well, but when the user cancels, the variable will still be set. So the next time the user wants to leave the page, the dialog won't be shown anymore.
Hope this is a little clear, and I hope someone has found a way around this?
In reaction to annakata: Yes, but you want the result of the dialog box to be used by the browser. So you might think using 'return bFlag' would do the trick (or event.returnValue = bFlag), but that gives you a second dialog box.
I've found a way around, thanks to this page. It's quite simple actually:
var onBeforeUnloadFired = false;
Use this global variable here:
if (!onBeforeUnloadFired) {
onBeforeUnloadFired = true;
event.returnValue = "You'll lose changes!";
}
window.setTimeout("ResetOnBeforeUnloadFired()", 1000);
And then implement that function:
function ResetOnBeforeUnloadFired() {
onBeforeUnloadFired = false;
}
So, in effect, use the flag, but reset it if the user clicks cancel. Not entirely what I would like, but haven't found anything better.
I haven't encountered this, but surely you could set the flag variable to be equal to the result of the dialog? If the user cancels the flag will therefore remain false.
var bFlag = window.confirm('Do you want to leave this page?');
IE supports an event on the document object called onstop. This event fires after the onbeforeunload event, but before the onunload event. This isn't exactly pertinent to your two dialogs question, but its still relevant to other people that might stumble on this thread ( as I did ).
The problem I was having, was that I needed to display a loading message upon the onbeforeunload event firing. This is all fine until the page has some sort of confirm dialog on it. The onbeforeunload event fires even if the user cancel's and remains on the page. The easiest thing for me to do was to move my "loading" display logic into a handler for document.onstop. On top of this, you have to check the readyState property of the document object, which is another IE-only field. If its "loading", it means the user is actually leaving the page. If its "complete", it means the user is staying.
If you are fine with just using IE, then you might be interested in the following.
document.onstop = function()
{
try
{
if( document.readyState != "complete" )
{
showLoadingDiv();
}
}
catch( error )
{
handleError( error );
}
}

Setting Focus with ASP.NET AJAX Control Toolkit

I'm using the AutoComplete control from the ASP.NET AJAX Control Toolkit and I'm experiencing an issue where the AutoComplete does not populate when I set the focus to the assigned textbox.
I've tried setting the focus in the Page_Load, Page_PreRender, and Page_Init events and the focus is set properly but the AutoComplete does not work. If I don't set the focus, everything works fine but I'd like to set it so the users don't have that extra click.
Is there a special place I need to set the focus or something else I need to do to make this work? Thanks.
We had exactly the same problem. What we had to do is write a script at the bottom of the page that quickly blurs then refocuses to the textbox. You can have a look at the (terribly hacky) solution here: http://www.drive.com.au
The textbox id is MainSearchBox_SearchTextBox. Have a look at about line 586 & you can see where I'm wiring up all the events (I'm actually using prototype for this bit.
Basically on the focus event of the textbox I set a global var called textBoxHasFocus to true and on the blur event I set it to false. The on the load event of the page I call this script:
if (textBoxHasFocus) {
$get("MainSearchBox_SearchTextBox").blur();
$get("MainSearchBox_SearchTextBox").focus();
}
This resets the textbox. It's really dodgy, but it's the only solution I could find
this is waste , its simple
this is what you need to do
controlId.focus(); in C#
controlID.focus() in VB
place this in page load or button_click section
eg. panel1.focus(); if panel1 has model popup extender attached to it, then we put this code in page load section
How are you setting focus? I haven't tried the specific scenario you've suggested, but here's how I set focus to my controls:
Public Sub SetFocus(ByVal ctrl As Control)
Dim sb As New System.Text.StringBuilder
Dim p As Control
p = ctrl.Parent
While (Not (p.GetType() Is GetType(System.Web.UI.HtmlControls.HtmlForm)))
p = p.Parent
End While
With sb
.Append("<script language='JavaScript'>")
.Append("function SetFocus()")
.Append("{")
.Append("document.")
.Append(p.ClientID)
.Append("['")
.Append(ctrl.UniqueID)
.Append("'].focus();")
.Append("}")
.Append("window.onload = SetFocus;")
.Append("")
.Append("</script")
.Append(">")
End With
ctrl.Page.RegisterClientScriptBlock("SetFocus", sb.ToString())
End Sub
So, I'm not sure what method you're using, but if it's different than mine, give that a shot and see if you still have a problem or not.
What I normally do is register a clientside script to run the below setFocusTimeout method from my codebehind method. When this runs, it waits some small amount of time and then calls the method that actually sets focus (setFocus). It's terribly hackish, but it seems you have to go a route like this to stop AJAX from stealing your focus.
function setFocusTimeout(controlID) {
focusControlID = controlID;
setTimeout("setFocus(focusControlID)", 100);
}
function setFocus() {
document.getElementById(focusControlID).focus();
}
I found the answers from Glenn Slaven and from Kris/Alex to get me closer to a solution to my particular problem with setting focus on an ASP.NET TextBox control that had an AutoCompleteExtender attached. The document.getElementById(focusControlID).focus() kept throwing a javascript error that implied document.getElementById was returning a null object. The focusControlID variable was returning the correct runtime ClientID value for the TextBox control. But for whatever reason, the document.getElementById function didn't like it.
My solution was to throw jQuery into the mix, as I was already using it to paint the background of any control that had focus, plus forcing the Enter key to tab through the form instead of firing a postback.
My setFocus function ended up looking like this:
function setFocus(focusControlID) {
$('#' + focusControlID).blur();
$('#' + focusControlID).focus();
}
This got rid of the javascript runtime error, put focus on the desired TextBox control, and placed the cursor within the control as well. Without first blurring then focusing, the control would be highlighted as if it had focus, but the cursor would not be sitting in the control yet. The user would still have to click inside the control to begin editing, which would be an UX annoyance.
I also had to increase the timeout from 100 to 300. Your mileage my vary...
I agree with everyone that this is a hack. But from the end-user's perspective, they don't see this code. The hack for them is if they have to manually click inside the control instead of just being automatically placed inside the control already and typing the first few letters to trigger the auto lookup functionality. So, hats off to all who provided their hacks.
I hope this is helpful to someone else.

Resources