Sharepoint 2013 People Picker Change event in Javascript - javascript

I want People picker Change Event in Javascript as i have to do some task if user is selected/changed in people picker using ClassName.
i have tried the following
$(".Assignedname").bind('input propertychange', function() {
alert("Onchange event" );
})
this fires when i type anything (i.e. text is changed ) , but not fires when user is selected in peoples picker.
Kindly give me some solution. thanks

Once the people picker is initialized, you can access it in the js dictionary and assign a function to the OnValueChangedClientScript property of the picker. The function accepts two parameters, where the second parameter (userInfo) is a collection of users in the picker
var picker = SPClientPeoplePicker.SPClientPeoplePickerDict[pickerId + "_TopSpan"];
picker.OnValueChangedClientScript = function (elementId, userInfo) {
for (var x = 0; x < userInfo.length; x++) {
console.log(userInfo[x].Key);
}
alert("Total number of " + userInfo.length + " users is selected")
};

You need to get the picker id for SharePoint Client People Picker change event. I have got the same using OnUserResolvedClientScript as below. Here to get the picker div I have followed the approach of getting it via the people picker text box id and the title name which you can get the by inspecting the element. put the below code in $(document).ready function. Happy Coding
SP.SOD.executeFunc('clientpeoplepicker.js', 'SPClientPeoplePicker', function() {
var pickerDiv = $("[id^='Employee_x0020_Name'][title='Employee Name']");
var picker = SPClientPeoplePicker.SPClientPeoplePickerDict[pickerDiv[0].id];
picker.OnUserResolvedClientScript = function(peoplePickerId, selectedUsersInfo) {
//It will get the desired display name of the people from picker div, similarly any other property can be accessed via selectedUsersInfo
var empname = selectedUsersInfo[0].DisplayText;
console.log(empname);
}
});

I used jQuery and a focusout event on the input field, instead, to achieve the same effect:
$('input[title="Title of my field"]').focusout(function() {
alert("Focusout event fired." );
doPeoplePickerStuff(); // function for doing validation
});
This has the advantage of being able to check the value of that field whenever they click on anything else - with the exception of the Submit button, if they click that immediately after typing in the field. Here's how I deal with that:
Create a new Submit button and hide the other one:
$('input[name*="diidIOSaveItem"]').parent().append('<input type="button" id="btnSubmit" onclick="doValidation()"></input>'); $('input[name*="diidIOSaveItem"]').hide();
Create the doValidation() function for your new Submit button:
function doValidation() {
doPeoplePickerStuff(); // do validation on the field here
if (personFound == true) {
$('input[name*="diidIOSaveItem"]').click(); // clicks the real button so it does what it normally would
}
}
If you're firing the event in order to grab its value and do validation on it, use:
var personFound = false;
function doPeoplePickerStuff() {
var personFieldSpan = $('span[id*="OriginalTitleOfMyField"]');
var personFieldValue = stripExtraTextFromPeoplePicker(personFieldSpan.text());
if (personFieldValue != "") { // you could do comparisons against the existing value, too, by getting the original value(s) via REST call
personFound = true;
}
}
function stripExtraTextFromPeoplePicker(person) {
var newPerson = person;
console.log("Span text: " + newPerson);
newPerson = newPerson.replace('Title of my field','');
newPerson = newPerson.replace('Enter a name or email address...','');
newPerson = newPerson.replace('Enter names or email addresses...','');
newPerson = newPerson.replace('xSuggestions are available. Use up and down arrows to select.','');
newPerson = newPerson.replace('Suggestions are available. Use up and down arrows to select.','');
newPerson = newPerson.replace('\r','');
newPerson = newPerson.replace('\n','');
newPerson = newPerson.replace('\t','');
newPerson = newPerson.trim();
return newPerson;
}

Related

Troubleshooting Conditional Form

I'm new to Javascript and trying to build a conditional form using bootstrap and JQuery. I would really appreciate the help as I've been working most of the day on this to no avail.
I'm trying to show the div with id physician (and subsequent field) when the select field with the name AppointmentType has a value of Orthopedic or Rheumatology. Here is the link to the live form.
Here is my javascript:
$( document ).ready(function() { //wait until body loads
//Inputs that determine what fields to show
var appttype = $('#secureform input:select[name=AppointmentType]');
var physician = document.getElementById("physician");
appttype.change(function(){ //when the Appointment Type changes
var value=this.value;
physician.addClass('hidden'); //hide everything and reveal as needed
if (value === 'Orthopedic' || value === 'Rheumatology'){
physician.removeClass('hidden'); //show doctors
}
else {}
});
});
These lines are going to cause errors (which you should see in your devtools console):
var appttype = $('#secureform input:select[name=AppointmentType]'); // `input:select` is not a valid selector and causes the rest of the script to fail
physician.addClass('hidden'); // `addClass` is a jQuery method, so this should be `$(physician).addClass('hidden')`
physician.removeClass('hidden');// `removeClass` is a jQuery method, so this should be `$(physician).removeClass('hidden')`
Correct those lines and it should work.
If it helps, I would write it like this:
$( document ).ready(function () {
//Inputs that determine what fields to show
var apptType = $('#secureform select[name="AppointmentType"]'); // dropped the `input:` part
var physician = document.getElementById('physician');
physician.classList.add('hidden'); //hide this initially, outside the change handler
apptType.change(function () { // when the Appointment Type changes
var value = $(this).val().toLowerCase(); // leave case-sensitivity out of it.
var showables = [ // using an array as I prefer using a simple `indexOf` for multiple comparisons
'orthopedic',
'rheumatology',
];
var isShowable = showables.indexOf(value) > -1;
physician.classList.toggle('hidden', !isShowable);
// or, the jQuery equivalent:
// $(physician).toggleClass('hidden', !isShowable);
});
});
Your selector is incorrect:
var appttype = $('#secureform input:select[name=AppointmentType]');
// this should be
var appttype = $('#secureform select[name=AppointmentType]');
Furthermore you are mixing jquery with vanilla JS. Your are using vanilla js here
var physician = document.getElementById("physician");
Physician is now a dom object and not a jquery object. You should use this instead:
var physician = $("#physician");
Additionally you should replace
var value=this.value;
with this
var value= $(this).val();

re-populate form, after saving form data to serialized array Javascript

I am creating a form that I want users to be able to edit. The user will fill the form, save that form, fill the form with the next entry, save that form, etc. A clickable div is created each time the form is saved so that the user can go back and see their inputs to ensure they are correct before final submission of all forms. I've been able to save the form data doing this:
var formArray = $('form#popsetForm').serializeArray();
My question: I would now like to fill the form back with the data in formArray when the user clicks on the div. Is there an easy command that will allow me to just provide the array as input and it will auto-fill the form? The below is not real code but what I'm hoping exists.
$('form#popsetForm').populate(formArray)
I don't know if a solution already exists but something like this should work with serializeArray.
function restoreForm(form, formArray) {
formArray.forEach(function (pair) {
var selector = `input[name="${ pair.name }"], textarea[name="${ pair.name }"]`
var input = $(form).find(selector)
input.val(pair.value);
})
}
https://jsfiddle.net/aycnx0gd/4/
Or like this for regular ol' formData
function restoreForm(form, formData) {
for (var key of formData.keys()) {
var selector = `input[name="${ key }"], textarea[name="${ key }"]`
var input = $(form).find(selector)
var newVal = formData.get(key)
input.val(newVal);
}
}
https://jsfiddle.net/aycnx0gd/2/
I would consider simply hiding the form from view, eliminating the need to repopulate it at all.
Your form submit handler might look something like this:
$('#some_common_parent_element_to_all_forms').on('submit', 'form', function() {
var $currentForm = $(this);
// not shown - your form submit logic here
// on success of form submittal execute following...
// hide submitted form
$currentForm.hide();
// was form submitted previously?
// if so, we don't want to generate a new form
if($currentForm.data('submitted') !== true) {
// clone form
var $newForm = $currentForm.clone();
// reset cloned form
$newForm.get(0).reset();
// mark submitted form as submitted
$currentForm.data('submitted', true);
// append new form to DOM
$('#some_common_parent_element_to_all_forms').append($newForm).show();
// create new div to be able to "navigate" to submitted form
var $formNavContainer = $('#some_element_that_holds_nav_divs');
var currentNavCount =
$formNavContainer.find('.form_navigation').length;
var formDisplayNum = currentNavCount + 1;
var $newNav =
$('<div class="form_navigation">Form ' + formDisplayNum + '</div>');
$newNav.data('target-form-index', currentNavCount);
$newNav.appendTo($formNavContainer);
} else {
// this form was previously submitted
// perhaps we just reveal most recently created form
$('#some_common_parent_element_to_all_forms form').last().show();
}
}
And a click handler for navigation divs may look like:
$('#some_element_that_holds_nav_divs').on('click', '.form_navigation', function() {
var $clickedNav = $(this);
var formIndex = $clickedNav.data('target-form-index');
var $allForms = $('#some_common_parent_element_to_all_forms form');
var $selectedForm = $allForms.get(formIndex);
$allForms.hide();
$selectedForm.show();
});
This approach will allow you to create X number of forms, each storing their own set of form data. "Navigating" between forms then simply becomes a matter of showing/hiding the individual forms.

CKEditor get table dialog class init Value in Set Up function of another element added on dialogDefinition

PLEASE READ QUESTION BEFORE READING CODE!!!
I've added a checkbox element on Dialog definition of the table dialog (it works). Now I want the checkbox to be checked by default when the table being edited has a certain class (which is usually visible on the advanced tab). According to the documentation, I should be able to do something like this in my setup function. I've tried many things and you could hopefully help me. This is my code.
CKEDITOR.on( 'dialogDefinition', function( evt )
{
var dialog = evt.data;
if(dialog.name == 'table' || dialog.name=='tableProperties')
{
// Get dialog definition.
var def = evt.data.definition;
var infoTab = def.getContents( 'info' );
infoTab.add(
{
type: 'checkbox',
id: 'myCheckBox',
label: 'Table Has Property',
setup: function()
{
//Class to look for if I successfully get the input's value
var classValueToLookFor = 'has-property';
// The current CKEditor Dialog Instance
var thisDialog = CKEDITOR.dialog.getCurrent();
// The Element whose value I want to get
var classElement = theDialog.getContentElement('advanced','advCSSClasses');
// Trying to Get Value of this class Element According to documentation
var containedClasses = theDialog.getValueOf('advanced','advCSSClasses');
// Trying to debug the value above
console.log(containedClasses); // This shows nothing
// Trying to debug InitValue which shows something according to prototype
console.log(classElement.getInitValue()); //This also shows nothing
//Checking if Element has the class I'm looking for to mark the checkbox
if(containedClasses.indexOf(classValueToLookFor) != -1)
{
//Check current checkbox since value has been found
this.setValue('checked');
}
}
onClick: function() // You can ignore this function, just put it in case you were wondering how I'm putting the has-property, might help someone else (works well) ;)
{
var checked = this.getValue();
var classValueToSet = 'has-property';
var thisDialog = CKEDITOR.dialog.getCurrent();
var containedClasses = theDialog.getValueOf('advanced','advCSSClasses');
if(checked)
{
if(containedClasses.indexOf(classValueToSet) != -1)
{
//console.log('already contains class: '+classValueToSet);
}
else
{
containedClasses += containedClasses+" "+classValueToSet;
}
}
else
{
if(containedClasses.indexOf(classValueToSet) != -1)
{
containedClasses = containedClasses.replace(classValueToSet,'');
}
else
{
//console.log('already removed class: '+classValueToSet);
}
}
thisDialog.setValueOf('advanced','advCSSClasses',containedClasses);
}
}
}
Here are some debug statements that can be helpful to add into the setup function and understand what is going on, you shouldn't need to go through all I've went through ;)
console.log('in setup function');
console.log(classElement);
console.log(classElement._);
console.log(classElement.getInitValue());
console.log(classElement.getInputElement());
var inputElement = classElement.getInputElement();
var inputElementId = inputElement.getId();
console.log($('#'+inputElementId+'.cke_dialog_ui_input_text'));
console.log(classElement.getInputElement().value);
It would be nice to test your answer before suggesting. Many of the things I've tried should work in theory, but are practically not working.
Alright, so finally after a few days of trial and error, this is what finally worked for me. Maybe it could be helpful to someone. I'm sure there should be a much cleaner way to do this. All the best to everyone.
setup: function()
{
//This current checkbox
var checkbox = this;
//the class I want to find on my table
var var classValueToLookFor = 'has-property';
//Current Dialog instance
var thisDialog = CKEDITOR.dialog.getCurrent();
//This code below gets a <td> element in the table
var startElement = thisDialog.getParentEditor().getSelection().getStartElement();
// This gets me the parent of the <td> element which is my current table instance
var parentTable = $(startElement.$.offsetParent);
//Finally check if the table has the property I'm looking for.
if(parentTable.hasClass(classValueToLookFor))
{
//Mark the checkbox
checkbox.setValue('checked');
}
}

Bootstrap TypeAhead.js prevent invalid entry

I am using the bootstrap typeahead.js feature for autocomplete capability for 'state' lookup. How can I best prevent individuals from typing all (and not successfully picking Alaska) before submitting the form?
Typeahead.js does not currently support this behavior.
You can use other libraries better suited for restricted options, for example Select2
However I have working fork of Typeahead that supports this.
See the JQuery example page here:
https://github.com/Svakinn/typeahead.js/blob/typeaheadSimple/Examples.md
Depending on your requirements you could enforce picking from valid options only and clearing any invalid input.
Start with creating a custom source which tracks search results:
var sync = false;
var current_results = [];
var current_q = '';
var selected_val = '';
function search(q, sync) {
current_q = q;
window.sync = sync;
engine.search(q, cust_sync);
}
function cust_sync(datums) {
current_results = datums;
sync(datums);
}
$('#typeahead').typeahead(
{
highlight: true,
minLength: 0
},
{
source: search // custom search engine
}
);
Then bind select and change event handlers.
$('#typeahead').bind('typeahead:change', function(ev) {
var current_val = $('#typeahead').val();
// user moved cursor out of input without selecting from the menu
if(current_val != selected_val){
// current query has search results
if(current_results.length)
// change input to the first valid search result
$('#typeahead').typeahead('val', current_results[0].name);
// no results for this query - clear input
else
$('#typeahead').typeahead('val', '');
}
});
$('#typeahead').bind('typeahead:select', function(ev, suggestion) {
selected_val = $('#typeahead').val(); // keep track of a selected value
});

Using action in Javascript to submit form

I'm trying to submit a form using javascript. This is the code I've used to set the action to the form and then submit it. These 2 lines are in the onclick method defined for a button.
document.form1.action = fin_string;
document.forms["form1"].submit();
The problem here is that the fin_string gets replaced by something else when I do this. For eg. when fin_string = "http://www.gmail.com" this works, however when I keep fin_string as some other string (relative to the current path with attached parameters) it gets changed. alert(fin_string), shows the string correctly but when I use the string to set the action on the form and submit it, it gets changed.
This is what I want the fin_string to be (relative to the current path)
remote-service/FeedMergerManualTrigger?locales=en_GB-en_SG&deleteOutputFile=Y&localFilePath=c:/go/
but this is what the browser goes to when I assign it an action and submit the form.
remote-service/FeedMergerManualTrigger?LMN=UK&ZJ=SG&localResourcesMode=on&EUPath=c:/go/&delete_op=Y.
Any idea what's going on?
Have such code instead, it will assign hidden form elements instead of adding to the query string thus it won't get changed:
var fin_string = "remote-service/FeedMergerManualTrigger";
var arrData = {"locales": "en_GB-en_SG", "deleteOutputFile": "Y", "localFilePath": "c:/go/"};
var oForm = document.forms["form1"];
oForm.action = fin_string;
for (var key in arrData)
AddOrUpdate(oForm, key, arrData[key]);
//encodeURIComponent(arrData[key])
oForm.submit();
function AddOrUpdate(oForm, sName, sValue) {
var oInput = oForm.elements[sName];
if (!oInput) {
oInput = document.createElement("input");
oInput.type = "hidden";
oInput.name = sName;
oForm.appendChild(oInput);
}
oInput.value = sValue;
}

Categories