/// /// /// /// //code from http://sptypescript.codeplex.com/ //BasicTasksJSOM.ts // Website tasks function retrieveWebsite(resultpanel:HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); clientContext.load(oWebsite); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Web site title: " + oWebsite.get_title(); } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function retrieveWebsiteProps(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); clientContext.load(oWebsite, "Description", "Created"); clientContext.executeQueryAsync(successHandler,errorHandler); function successHandler() { resultpanel.innerHTML = "Description: " + oWebsite.get_description() + "
Date created: " + oWebsite.get_created(); } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function writeWebsiteProps(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); oWebsite.set_description("This is an updated description."); oWebsite.update(); clientContext.load(oWebsite, "Description"); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Web site description: " + oWebsite.get_description(); } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } // Lists tasks function readAllProps(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var collList = oWebsite.get_lists(); clientContext.load(collList); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { var listEnumerator = collList.getEnumerator(); var listInfo = ""; while (listEnumerator.moveNext()) { var oList = listEnumerator.get_current(); listInfo += "Title: " + oList.get_title() + " Created: " + oList.get_created().toString() + "
"; } resultpanel.innerHTML = listInfo; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function readSpecificProps(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var collList = oWebsite.get_lists(); clientContext.load(collList, "Include(Title, Id)"); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { var listEnumerator = collList.getEnumerator(); var listInfo = ""; while (listEnumerator.moveNext()) { var oList = listEnumerator.get_current(); listInfo += "Title: " + oList.get_title() + " ID: " + oList.get_id().toString() + "
"; } resultpanel.innerHTML = listInfo; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function readColl(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var collList = oWebsite.get_lists(); var listInfoCollection = clientContext.loadQuery(collList, "Include(Title, Id)"); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { var listInfo = ""; for (var i = 0; i < listInfoCollection.length; i++) { var oList = listInfoCollection[i]; listInfo += "Title: " + oList.get_title() + " ID: " + oList.get_id().toString() + "
"; } resultpanel.innerHTML = listInfo; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function readFilter(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var collList = oWebsite.get_lists(); var listInfoArray = clientContext.loadQuery(collList, "Include(Title,Fields.Include(Title,InternalName))"); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { for (var i = 0; i < listInfoArray.length; i++) { var oList = listInfoArray[i]; var collField = oList.get_fields(); var fieldEnumerator = collField.getEnumerator(); var listInfo = ""; while (fieldEnumerator.moveNext()) { var oField = fieldEnumerator.get_current(); var regEx = new RegExp("name", "ig"); if (regEx.test(oField.get_internalName())) { listInfo += "List: " + oList.get_title() + "
    Field Title: " + oField.get_title() + "
    Field Internal name: " + oField.get_internalName(); } } } resultpanel.innerHTML = listInfo; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } // Create, update and delete lists function createList(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var listCreationInfo = new SP.ListCreationInformation(); listCreationInfo.set_title("My Announcements List"); listCreationInfo.set_templateType(SP.ListTemplateType.announcements); var oList = oWebsite.get_lists().add(listCreationInfo); clientContext.load(oList); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the list."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function updateList(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("My Announcements List"); oList.set_description("New Announcements List"); oList.update(); clientContext.load(oList); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Check the description in the list."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function addField(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("My Announcements List"); var oField = oList.get_fields().addFieldAsXml( "", true, SP.AddFieldOptions.defaultValue ); var fieldNumber = clientContext.castTo(oField, SP.FieldNumber); fieldNumber.set_maximumValue(100); fieldNumber.set_minimumValue(35); fieldNumber.update(); clientContext.load(oField); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "The list with a new field."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function deleteList(resultpanel: HTMLElement) { var listTitle = "My Announcements List"; var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle(listTitle); oList.deleteObject(); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = listTitle + " deleted."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } // Create, update and delete folders function createFolder(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Shared Documents"); var itemCreateInfo = new SP.ListItemCreationInformation(); itemCreateInfo.set_underlyingObjectType(SP.FileSystemObjectType.folder); itemCreateInfo.set_leafName("My new folder!"); var oListItem = oList.addItem(itemCreateInfo); oListItem.update(); clientContext.load(oListItem); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the document library to see your new folder."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function updateFolder(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Shared Documents"); var oListItem = oList.getItemById(1); oListItem.set_item("FileLeafRef", "My updated folder"); oListItem.update(); clientContext.load(oListItem); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the document library to see your updated folder."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function deleteFolder(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Shared Documents"); var oListItem = oList.getItemById(1); oListItem.deleteObject(); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the document library to make sure the folder is no longer there."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } // List item tasks function readItems(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Announcements"); var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml( '' + '1' + '10' ); var collListItem = oList.getItems(camlQuery); clientContext.load(collListItem); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { var listItemEnumerator = collListItem.getEnumerator(); var listItemInfo = ""; while (listItemEnumerator.moveNext()) { var oListItem = listItemEnumerator.get_current(); listItemInfo += "ID: " + oListItem.get_id() + "
" + "Title: " + oListItem.get_item("Title") + "
" + "Body: " + oListItem.get_item("Body") + "
"; } resultpanel.innerHTML = listItemInfo; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function readInclude(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Announcements"); var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml('100'); var collListItem = oList.getItems(camlQuery); clientContext.load(collListItem, "Include(Id, DisplayName, HasUniqueRoleAssignments)"); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { var listItemEnumerator = collListItem.getEnumerator(); var listItemInfo = ""; while (listItemEnumerator.moveNext()) { var oListItem = listItemEnumerator.get_current(); listItemInfo += "ID: " + oListItem.get_id() + "
" + "Display name: " + oListItem.get_displayName() + "
" + "Unique role assignments: " + oListItem.get_hasUniqueRoleAssignments() + "
"; } resultpanel.innerHTML = listItemInfo; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } // Create, update and delete list items function createListItem(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Announcements"); var itemCreateInfo = new SP.ListItemCreationInformation(); var oListItem = oList.addItem(itemCreateInfo); oListItem.set_item("Title", "My New Item!"); oListItem.set_item("Body", "Hello World!"); oListItem.update(); clientContext.load(oListItem); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the list to see your new item."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function updateListItem(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Announcements"); var oListItem = oList.getItemById(1); oListItem.set_item("Title", "My updated title"); oListItem.update(); clientContext.load(oListItem); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the list to see your updated item."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } function deleteListItem(resultpanel: HTMLElement) { var clientContext = SP.ClientContext.get_current(); var oWebsite = clientContext.get_web(); var oList = oWebsite.get_lists().getByTitle("Announcements"); var oListItem = oList.getItemById(1); oListItem.deleteObject(); clientContext.executeQueryAsync( successHandler, errorHandler ); function successHandler() { resultpanel.innerHTML = "Go to the list to make sure the item is no longer there."; } function errorHandler() { resultpanel.innerHTML = "Request failed: " + arguments[1].get_message(); } } /** Lightweight client-side rendering template overrides.*/ module CSR { export interface UpdatedValueCallback { (value: any, fieldSchema?: SPClientTemplates.FieldSchema_InForm): void; } /** Creates new overrides. Call .register() at the end.*/ export function override(listTemplateType?: number, baseViewId?: number|string): ICSR { return new csr(listTemplateType, baseViewId) .onPreRender(hookFormContext) .onPostRender(fixCsrCustomLayout); function hookFormContext(ctx: IFormRenderContexWithHook) { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { for (var i = 0; i < ctx.ListSchema.Field.length; i++) { var fieldSchemaInForm = ctx.ListSchema.Field[i]; if (!ctx.FormContextHook) { ctx.FormContextHook = {} var oldRegisterGetValueCallback = ctx.FormContext.registerGetValueCallback; ctx.FormContext.registerGetValueCallback = (fieldName, callback) => { ctx.FormContextHook[fieldName].getValue = callback; oldRegisterGetValueCallback(fieldName, callback); }; var oldUpdateControlValue = ctx.FormContext.updateControlValue; ctx.FormContext.updateControlValue = (fieldName: string, value: any) => { oldUpdateControlValue(fieldName, value); var hookedContext = ensureFormContextHookField(ctx.FormContextHook, fieldName); hookedContext.lastValue = value; var updatedCallbacks = ctx.FormContextHook[fieldName].updatedValueCallbacks; for (var i = 0; i < updatedCallbacks.length; i++) { updatedCallbacks[i](value, hookedContext.fieldSchema); } } } ensureFormContextHookField(ctx.FormContextHook, fieldSchemaInForm.Name).fieldSchema = fieldSchemaInForm; } } } function fixCsrCustomLayout(ctx: SPClientTemplates.RenderContext_Form) { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.Invalid || ctx.ControlMode == SPClientTemplates.ClientControlMode.View) { return; } if (ctx.ListSchema.Field.length > 1) { var wpq = ctx.FormUniqueId; var webpart = $get('WebPart' + wpq); var forms = webpart.getElementsByClassName('ms-formtable'); if (forms.length > 0) { var placeholder = $get(wpq + 'ClientFormTopContainer'); var fragment = document.createDocumentFragment(); for (var i = 0; i < placeholder.children.length; i++) { fragment.appendChild(placeholder.children.item(i)); } var form = forms.item(0); form.parentNode.replaceChild(fragment, form); } var old = ctx.CurrentItem; ctx.CurrentItem = ctx.ListData.Items[0]; var fields = ctx.ListSchema.Field; for (var j = 0; j < fields.length; j++) { var field = fields[j]; var pHolderId = wpq + ctx.FormContext.listAttributes.Id + field.Name; var span = $get(pHolderId); if (span) { span.outerHTML = ctx.RenderFieldByName(ctx, field.Name); } } ctx.CurrentItem = old; } } } //typescripttempltes.ts declare var Strings:any; export function getFieldValue(ctx: SPClientTemplates.RenderContext_Form, fieldName: string): any { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { var contextWithHook = ctx; if (contextWithHook.FormContextHook && contextWithHook.FormContextHook[fieldName] && contextWithHook.FormContextHook[fieldName].getValue) { return contextWithHook.FormContextHook[fieldName].getValue(); } } return null; } export function getFieldSchema(ctx: SPClientTemplates.RenderContext_Form, fieldName: string): SPClientTemplates.FieldSchema_InForm { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { var contextWithHook = ctx; if (contextWithHook.FormContextHook && contextWithHook.FormContextHook[fieldName]) { return contextWithHook.FormContextHook[fieldName].fieldSchema; } } return null; } export function addUpdatedValueCallback(ctx: SPClientTemplates.RenderContext_Form, fieldName: string, callback: UpdatedValueCallback): void { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { var contextWithHook = ctx; if (contextWithHook.FormContextHook) { var f = ensureFormContextHookField(contextWithHook.FormContextHook, fieldName); var callbacks = f.updatedValueCallbacks; if (callbacks.indexOf(callback) == -1) { callbacks.push(callback); if (f.lastValue) { callback(f.lastValue, f.fieldSchema); } } } } } export function removeUpdatedValueCallback(ctx: SPClientTemplates.RenderContext_Form, fieldName: string, callback: UpdatedValueCallback): void { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { var contextWithHook = ctx; if (contextWithHook.FormContextHook) { var callbacks = ensureFormContextHookField(contextWithHook.FormContextHook, fieldName).updatedValueCallbacks; var index = callbacks.indexOf(callback); if (index != -1) { callbacks.splice(index, 1); } } } } export function getControl(schema: SPClientTemplates.FieldSchema_InForm): HTMLInputElement { var id = schema.Name + '_' + schema.Id + '_$' + schema.FieldType + 'Field'; //TODO: Handle different input types return $get(id); } export function getFieldTemplate(field: SPClientTemplates.FieldSchema, mode: SPClientTemplates.ClientControlMode): SPClientTemplates.FieldCallback { var ctx = { ListSchema: { Field: [field] }, FieldControlModes: {} }; ctx.FieldControlModes[field.Name] = mode; var templates = SPClientTemplates.TemplateManager.GetTemplates(ctx); return templates.Fields[field.Name]; } class csr implements ICSR, SPClientTemplates.TemplateOverridesOptions { public Templates: SPClientTemplates.TemplateOverrides; public OnPreRender: SPClientTemplates.RenderCallback[]; public OnPostRender: SPClientTemplates.RenderCallback[]; private IsRegistered: boolean; constructor(public ListTemplateType?: number, public BaseViewID?: any) { this.Templates = { Fields: {} }; this.OnPreRender = [] ; this.OnPostRender = []; this.IsRegistered = false; } /* tier 1 methods */ view(template: any): ICSR { this.Templates.View = template; return this; } item(template: any): ICSR { this.Templates.Item = template; return this; } header(template: any): ICSR { this.Templates.Header = template; return this; } body(template: any): ICSR { this.Templates.Body = template; return this; } footer(template: any): ICSR { this.Templates.Footer = template; return this; } fieldView(fieldName: string, template: any): ICSR { this.Templates.Fields[fieldName] = this.Templates.Fields[fieldName] || {}; this.Templates.Fields[fieldName].View = template; return this; } fieldDisplay(fieldName: string, template: any): ICSR { this.Templates.Fields[fieldName] = this.Templates.Fields[fieldName] || {}; this.Templates.Fields[fieldName].DisplayForm = template; return this; } fieldNew(fieldName: string, template: any): ICSR { this.Templates.Fields[fieldName] = this.Templates.Fields[fieldName] || {}; this.Templates.Fields[fieldName].NewForm = template; return this; } fieldEdit(fieldName: string, template: any): ICSR { this.Templates.Fields[fieldName] = this.Templates.Fields[fieldName] || {}; this.Templates.Fields[fieldName].EditForm = template; return this; } /* tier 2 methods */ template(name: string, template: any): ICSR { this.Templates[name] = template; return this; } fieldTemplate(fieldName: string, name: string, template: any): ICSR { this.Templates.Fields[fieldName] = this.Templates.Fields[fieldName] || {}; this.Templates.Fields[fieldName][name] = template; return this; } /* common */ onPreRender(...callbacks: { (ctx: SPClientTemplates.RenderContext): void; }[]): ICSR { for (var i = 0; i < callbacks.length; i++) { this.OnPreRender.push(callbacks[i]); } return this; } onPostRender(...callbacks: { (ctx: SPClientTemplates.RenderContext): void; }[]): ICSR { for (var i = 0; i < callbacks.length; i++) { this.OnPostRender.push(callbacks[i]); } return this; } onPreRenderField(field: string, callback: { (schema: SPClientTemplates.FieldSchema, ctx: SPClientTemplates.RenderContext): void; }): ICSR { return this.onPreRender((ctx: SPClientTemplates.RenderContext) => { var ctxInView = ctx; //ListSchema schma exists in Form and in View render context var fields = ctxInView.ListSchema.Field; if (fields) { for (var i = 0; i < fields.length; i++) { if (fields[i].Name === field) { callback(fields[i], ctx); } } } }); } onPostRenderField(field: string, callback: { (schema: SPClientTemplates.FieldSchema, ctx: SPClientTemplates.RenderContext): void; }): ICSR { return this.onPostRender((ctx: SPClientTemplates.RenderContext) => { var ctxInView = ctx; //ListSchema schma exists in Form and in View render context var fields = ctxInView.ListSchema.Field; if (fields) { for (var i = 0; i < fields.length; i++) { if (fields[i].Name === field) { callback(fields[i], ctx); } } } }); } makeReadOnly(fieldName: string): ICSR { return this .onPreRenderField(fieldName, (schema, ctx) => { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.Invalid || ctx.ControlMode == SPClientTemplates.ClientControlMode.DisplayForm) return; (schema).ReadOnlyField = true; (schema).ReadOnly = "TRUE"; if (ctx.ControlMode == SPClientTemplates.ClientControlMode.View) { var ctxInView = ctx; if (ctxInView.inGridMode) { //TODO: Disable editing in grid mode } } else { var ctxInForm = ctx; if (schema.Type != 'User' && schema.Type != 'UserMulti') { var template = getFieldTemplate(schema, SPClientTemplates.ClientControlMode.DisplayForm); ctxInForm.Templates.Fields[fieldName] = template; ctxInForm.FormContext.registerGetValueCallback(fieldName, () => ctxInForm.ListData.Items[0][fieldName]); } } }) .onPostRenderField(fieldName, (schema: SPClientTemplates.FieldSchema_InForm_User, ctx) => { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { if (schema.Type == 'User' || schema.Type == 'UserMulti') { SP.SOD.executeFunc('clientpeoplepicker.js', 'SPClientPeoplePicker', () => { var topSpanId = schema.Name + '_' + schema.Id + '_$ClientPeoplePicker'; var retryCount = 10; var callback = () => { var pp = SPClientPeoplePicker.SPClientPeoplePickerDict[topSpanId]; if (!pp) { if (retryCount--) setTimeout(callback, 1); } else { pp.SetEnabledState(false); pp.DeleteProcessedUser = function () { }; } }; callback(); }); } } }); } makeHidden(fieldName: string): ICSR { return this.onPreRenderField(fieldName, (schema, ctx) => { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.Invalid) return; (schema).Hidden = true; if (ctx.ControlMode == SPClientTemplates.ClientControlMode.View) { var ctxInView = ctx; if (ctxInView.inGridMode) { //TODO: Hide item in grid mode } else { ctxInView.ListSchema.Field.splice(ctxInView.ListSchema.Field.indexOf(schema), 1); } } else { var ctxInForm = ctx; var pHolderId = ctxInForm.FormUniqueId + ctxInForm.FormContext.listAttributes.Id + fieldName; var placeholder = $get(pHolderId); var current = placeholder; while (current.tagName.toUpperCase() !== "TR") { current = current.parentElement; } var row = current; row.style.display = 'none'; } }); } filteredLookup(fieldName: string, camlFilter: string, listname?: string, lookupField?: string): ICSR { return this.fieldEdit(fieldName, SPFieldCascadedLookup_Edit) .fieldNew(fieldName, SPFieldCascadedLookup_Edit); function SPFieldCascadedLookup_Edit(rCtx: SPClientTemplates.RenderContext_FieldInForm) { var parseRegex = /\{[^\}]+\}/g; var dependencyExpressions: string[] = []; var result: RegExpExecArray; while ((result = parseRegex.exec(camlFilter))) { dependencyExpressions.push(stripBraces(result[0])); } var dependencyValues: { [expr: string]: string } = {}; var _dropdownElt: HTMLSelectElement; var _myData: SPClientTemplates.ClientFormContext; if (rCtx == null) return ''; _myData = SPClientTemplates.Utility.GetFormContextForCurrentField(rCtx); if (_myData == null || _myData.fieldSchema == null) return ''; var _schema = _myData.fieldSchema; var validators = new SPClientForms.ClientValidation.ValidatorSet(); validators.RegisterValidator(new BooleanValueValidator(() => _optionsLoaded, "Wait until lookup values loaded and try again")); if (_myData.fieldSchema.Required) { validators.RegisterValidator(new SPClientForms.ClientValidation.RequiredValidator()); } _myData.registerClientValidator(_myData.fieldName, validators); var _dropdownId = _myData.fieldName + '_' + _myData.fieldSchema.Id + '_$LookupField'; var _valueStr = _myData.fieldValue != null ? _myData.fieldValue : ''; var _selectedValue = SPClientTemplates.Utility.ParseLookupValue(_valueStr).LookupId; var _noValueSelected = _selectedValue == 0; var _optionsLoaded = false; var pendingLoads = 0; if (_noValueSelected) _valueStr = ''; _myData.registerInitCallback(_myData.fieldName, InitLookupControl); _myData.registerFocusCallback(_myData.fieldName, function () { if (_dropdownElt != null) _dropdownElt.focus(); }); _myData.registerValidationErrorCallback(_myData.fieldName, function (errorResult) { SPFormControl_AppendValidationErrorMessage(_dropdownId, errorResult); }); _myData.registerGetValueCallback(_myData.fieldName, GetCurrentLookupValue); _myData.updateControlValue(_myData.fieldName, _valueStr); return BuildLookupDropdownControl(); function InitLookupControl() { _dropdownElt = document.getElementById(_dropdownId); if (_dropdownElt != null) AddEvtHandler(_dropdownElt, "onchange", OnLookupValueChanged); SP.SOD.executeFunc('sp.js', 'SP.ClientContext', () => { bindDependentControls(dependencyExpressions); loadOptions(true); }); } function BuildLookupDropdownControl() { var result = ''; result += '
'; return result; } function OnLookupValueChanged() { if (_optionsLoaded) { if (_dropdownElt != null) { _myData.updateControlValue(_myData.fieldName, GetCurrentLookupValue()); _selectedValue = parseInt(_dropdownElt.value, 10); } } } function GetCurrentLookupValue() { if (_dropdownElt == null) return ''; return _dropdownElt.value == '0' || _dropdownElt.value == '' ? '' : _dropdownElt.value + ';#' + _dropdownElt.options[_dropdownElt.selectedIndex].text; } function stripBraces(input: string): string { return input.substring(1, input.length - 1); } function getDependencyValue(expr: string, value: string, listId: string, expressionParts: string[], callback: () => void) { var isLookupValue = !!listId; if (isLookupValue) { var lookup = SPClientTemplates.Utility.ParseLookupValue(value); if (expressionParts.length == 1 && expressionParts[0] == 'Value') { value = lookup.LookupValue; expressionParts.shift(); } else { value = lookup.LookupId.toString(); } } if (expressionParts.length == 0) { dependencyValues[expr] = value; callback(); } else { var ctx = SP.ClientContext.get_current(); var web = ctx.get_web(); //TODO: Handle lookup to another web var list = web.get_lists().getById(listId); var item = list.getItemById(parseInt(value, 10)); var field = list.get_fields().getByInternalNameOrTitle(expressionParts.shift()); ctx.load(item); ctx.load(field); ctx.executeQueryAsync((o, e) => { var value = item.get_item(field.get_internalName()); if (field.get_typeAsString() == 'Lookup') { field = ctx.castTo(field, SP.FieldLookup); var lookup = (value); value = lookup.get_lookupId() + ';#' + lookup.get_lookupValue(); listId = (field).get_lookupList(); } getDependencyValue(expr, value, listId, expressionParts, callback); }, (o, args) => { console.log(args.get_message()); }); } } function bindDependentControls(dependencyExpressions: string[]) { dependencyExpressions.forEach(expr => { var exprParts = expr.split("."); var field = exprParts.shift(); CSR.addUpdatedValueCallback(rCtx, field, (v, s) => { getDependencyValue(expr, v, (s).LookupListId, exprParts.slice(0), loadOptions); }); }); } function loadOptions(isFirstLoad?: boolean) { _optionsLoaded = false; pendingLoads++; var ctx = SP.ClientContext.get_current(); //TODO: Handle lookup to another web var web = ctx.get_web(); var listId = _schema.LookupListId; var list = !listname ? web.get_lists().getById(listId) : web.get_lists().getByTitle(listname); var query = new SP.CamlQuery(); var predicate = camlFilter.replace(parseRegex, (v, a) => { var expr = stripBraces(v); return dependencyValues[expr] ? dependencyValues[expr] : ''; }); //TODO: Handle ShowField attribure if (predicate.substr(0, 5) == '' + predicate + ' ' + ''); } var results = list.getItems(query); ctx.load(results); ctx.executeQueryAsync((o, e) => { var selected = false; while (_dropdownElt.options.length) { _dropdownElt.options.remove(0); } if (!_schema.Required) { var defaultOpt = new Option(Strings.STS.L_LookupFieldNoneOption, '0', selected, selected); _dropdownElt.options.add(defaultOpt); selected = _selectedValue == 0; } var isEmptyList = true; var enumerator = results.getEnumerator(); while (enumerator.moveNext()) { var c = enumerator.get_current(); var id: number; var text: string; if (!lookupField) { id = c.get_id(); text = c.get_item('Title'); } else { var value = c.get_item(lookupField); id = value.get_lookupId(); text = value.get_lookupValue(); } var isSelected = _selectedValue == id; if (isSelected) { selected = true; } var opt = new Option(text, id.toString(), isSelected, isSelected); _dropdownElt.options.add(opt); isEmptyList = false; } pendingLoads--; _optionsLoaded = true; if (!pendingLoads) { if (isFirstLoad) { if (_selectedValue == 0 && !selected) { _dropdownElt.selectedIndex = 0; OnLookupValueChanged(); } } else { if (_selectedValue != 0 && !selected) { _dropdownElt.selectedIndex = 0; } OnLookupValueChanged(); } } }, (o, args) => { console.log(args.get_message()); }); } } } koEditField(fieldName: string, template: string, vm: IKoFieldInForm, dependencyFields?: string[]): ICSR { return this.fieldEdit(fieldName, koEditField_Edit) .fieldNew(fieldName, koEditField_Edit); function koEditField_Edit(rCtx: SPClientTemplates.RenderContext_FieldInForm) { if (rCtx == null) return ''; var _myData = SPClientTemplates.Utility.GetFormContextForCurrentField(rCtx); if (_myData == null || _myData.fieldSchema == null) return ''; var elementId = _myData.fieldName + '_' + _myData.fieldSchema.Id + '_$' + _myData.fieldSchema.Type; vm.renderingContext = rCtx; if (dependencyFields) { dependencyFields.forEach(dependencyField => { if (!vm[dependencyField]) { vm[dependencyField] = ko.observable(CSR.getFieldValue(rCtx, dependencyField)); } CSR.addUpdatedValueCallback(rCtx, dependencyField, v => { vm[dependencyField](v); }); }); } if (!vm.value) { vm.value = ko.observable(); } vm.value.subscribe(v => { _myData.updateControlValue(fieldName, v); }); _myData.registerGetValueCallback(fieldName, () => vm.value()); _myData.registerInitCallback(fieldName, () => { ko.applyBindings(vm, $get(elementId)); }); return '
'+template+'
'; } } computedValue(targetField: string, transform: (...values: string[]) => string, ...sourceField: string[]): ICSR { var dependentValues: { [field: string]: string } = {}; return this.onPostRenderField(targetField, (schema, ctx: SPClientTemplates.RenderContext_FieldInForm) => { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) { var targetControl = CSR.getControl(schema); sourceField.forEach((field) => { CSR.addUpdatedValueCallback(ctx, field, v => { dependentValues[field] = v; targetControl.value = transform.apply(this, sourceField.map(n => dependentValues[n] || '')); }); }); } }); } setInitialValue(fieldName: string, value: any, ignoreNull?: boolean): ICSR { if (value || !ignoreNull) { return this.onPreRenderField(fieldName, (schema, ctx: SPClientTemplates.RenderContext_FieldInForm) => { ctx.ListData.Items[0][fieldName] = value; }); } else { return this; } } autofill(fieldName: string, init: (ctx: IAutoFillFieldContext) => () => void): ICSR { return this .fieldNew(fieldName, SPFieldLookup_Autofill_Edit) .fieldEdit(fieldName, SPFieldLookup_Autofill_Edit); function SPFieldLookup_Autofill_Edit(rCtx: SPClientTemplates.RenderContext_FieldInForm) { if (rCtx == null) return ''; var _myData = SPClientTemplates.Utility.GetFormContextForCurrentField(rCtx); if (_myData == null || _myData.fieldSchema == null) return ''; var _autoFillControl: SPClientAutoFill; var _textInputElt: HTMLInputElement; var _textInputId = _myData.fieldName + '_' + _myData.fieldSchema.Id + '_$' + _myData.fieldSchema.Type + 'Field'; var _autofillContainerId = _myData.fieldName + '_' + _myData.fieldSchema.Id + '_$AutoFill'; var validators = new SPClientForms.ClientValidation.ValidatorSet(); if (_myData.fieldSchema.Required) { validators.RegisterValidator(new SPClientForms.ClientValidation.RequiredValidator()); } _myData.registerClientValidator(_myData.fieldName, validators); _myData.registerInitCallback(_myData.fieldName, initAutoFillControl); _myData.registerFocusCallback(_myData.fieldName, function () { if (_textInputElt != null) _textInputElt.focus(); }); _myData.registerValidationErrorCallback(_myData.fieldName, function (errorResult) { SPFormControl_AppendValidationErrorMessage(_textInputId, errorResult); }); _myData.registerGetValueCallback(_myData.fieldName, () => _myData.fieldValue); _myData.updateControlValue(_myData.fieldName, _myData.fieldValue); return buildAutoFillControl(); function initAutoFillControl() { _textInputElt = document.getElementById(_textInputId); SP.SOD.executeFunc("autofill.js", "SPClientAutoFill", () => { _autoFillControl = new SPClientAutoFill(_textInputId, _autofillContainerId, (_) => callback()); var callback = init({ renderContext: rCtx, fieldContext: _myData, autofill: _autoFillControl, control: _textInputElt, }); //_autoFillControl.AutoFillMinTextLength = 2; //_autoFillControl.VisibleItemCount = 15; //_autoFillControl.AutoFillTimeout = 500; }); } //function OnPopulate(targetElement: HTMLInputElement) { //} //function OnLookupValueChanged() { // _myData.updateControlValue(_myData.fieldName, GetCurrentLookupValue()); //} //function GetCurrentLookupValue() { // return _valueStr; //} function buildAutoFillControl() { var result: string[] = []; result.push('
'); result.push(''); result.push("
"); result.push("
"); return result.join(""); } } } seachLookup(fieldName: string): ICSR { return this.autofill(fieldName, (ctx: IAutoFillFieldContext) => { var _myData = ctx.fieldContext; var _schema = _myData.fieldSchema; if (_myData.fieldSchema.Type != 'Lookup') { return null; } var _valueStr = _myData.fieldValue != null ? _myData.fieldValue : ''; var _selectedValue = SPClientTemplates.Utility.ParseLookupValue(_valueStr); var _noValueSelected = _selectedValue.LookupId == 0; ctx.control.value = _selectedValue.LookupValue; $addHandler(ctx.control, "blur", _ => { if (ctx.control.value == '') { _myData.fieldValue = ''; _myData.updateControlValue(fieldName, _myData.fieldValue); } }); if (_noValueSelected) _myData.fieldValue = ''; var _autoFillControl = ctx.autofill; _autoFillControl.AutoFillMinTextLength = 2; _autoFillControl.VisibleItemCount = 15; _autoFillControl.AutoFillTimeout = 500; return () => { var value = ctx.control.value; _autoFillControl.PopulateAutoFill([AutoFillOptionBuilder.buildLoadingItem('Please wait...')], onSelectItem); SP.SOD.executeFunc("sp.search.js", "Microsoft.SharePoint.Client.Search.Query", () => { var Search = Microsoft.SharePoint.Client.Search.Query; var ctx = SP.ClientContext.get_current(); var query = new Search.KeywordQuery(ctx); query.set_rowLimit(_autoFillControl.VisibleItemCount); query.set_queryText('contentclass:STS_ListItem ListID:{' + _schema.LookupListId + '} ' + value); var selectProps = query.get_selectProperties(); selectProps.clear(); //TODO: Handle ShowField attribute selectProps.add('Title'); selectProps.add('ListItemId'); var executor = new Search.SearchExecutor(ctx); var result = executor.executeQuery(query); ctx.executeQueryAsync( () => { //TODO: Discover proper way to load collection var tableCollection = new Search.ResultTableCollection(); tableCollection.initPropertiesFromJson(result.get_value()); var relevantResults = tableCollection.get_item(0); var rows = relevantResults.get_resultRows(); var items = []; for (var i = 0; i < rows.length; i++) { items.push(AutoFillOptionBuilder.buildOptionItem(parseInt(rows[i]["ListItemId"], 10), rows[i]["Title"])); } items.push(AutoFillOptionBuilder.buildSeparatorItem()); if (relevantResults.get_totalRows() == 0) items.push(AutoFillOptionBuilder.buildFooterItem("No results. Please refine your query.")); else items.push(AutoFillOptionBuilder.buildFooterItem("Showing " + rows.length + " of" + relevantResults.get_totalRows() + " items!")); _autoFillControl.PopulateAutoFill(items, onSelectItem); }, (sender, args) => { _autoFillControl.PopulateAutoFill([AutoFillOptionBuilder.buildFooterItem("Error executing query/ See log for details.")], onSelectItem); console.log(args.get_message()); }); }); } function onSelectItem(targetInputId, item: ISPClientAutoFillData) { var targetElement = ctx.control; targetElement.value = item[SPClientAutoFill.DisplayTextProperty]; _selectedValue.LookupId = item[SPClientAutoFill.KeyProperty]; _selectedValue.LookupValue = item[SPClientAutoFill.DisplayTextProperty]; _myData.fieldValue = item[SPClientAutoFill.KeyProperty] + ';#' + item[SPClientAutoFill.TitleTextProperty]; _myData.updateControlValue(_myData.fieldSchema.Name, _myData.fieldValue); } }); } lookupAddNew(fieldName: string, prompt: string, showDialog?: boolean, contentTypeId?: string): ICSR { return this.onPostRenderField(fieldName, (schema: SPClientTemplates.FieldSchema_InForm_Lookup, ctx: SPClientTemplates.RenderContext_FieldInForm) => { if (ctx.ControlMode == SPClientTemplates.ClientControlMode.EditForm || ctx.ControlMode == SPClientTemplates.ClientControlMode.NewForm) var control = CSR.getControl(schema); if (control) { var weburl = _spPageContextInfo.webServerRelativeUrl; if (weburl[weburl.length - 1] == '/') { weburl = weburl.substring(0, weburl.length - 1); } var newFormUrl = weburl + '/_layouts/listform.aspx/listform.aspx?PageType=8' + "&ListId=" + encodeURIComponent('{' + schema.LookupListId + '}'); if (contentTypeId) { newFormUrl += '&ContentTypeId=' + contentTypeId; } var link = document.createElement('a'); link.href = "javascript:NewItem2(event, \'" + newFormUrl + "&Source=" + encodeURIComponent(document.location.href) + "')"; link.textContent = prompt; if (control.nextElementSibling) { control.parentElement.insertBefore(link, control.nextElementSibling); } else { control.parentElement.appendChild(link); } if (showDialog) { $addHandler(link, "click", (e: Sys.UI.DomEvent) => { SP.SOD.executeFunc('sp.ui.dialog.js', 'SP.UI.ModalDialog.ShowPopupDialog', () => { SP.UI.ModalDialog.ShowPopupDialog(newFormUrl); }); e.stopPropagation(); e.preventDefault(); }); } } }); } register() { if (!this.IsRegistered) { SPClientTemplates.TemplateManager.RegisterTemplateOverrides(this); this.IsRegistered = true; } } } export class AutoFillOptionBuilder { static buildFooterItem(title: string): ISPClientAutoFillData { var item = {}; item[SPClientAutoFill.DisplayTextProperty] = title; item[SPClientAutoFill.MenuOptionTypeProperty] = SPClientAutoFill.MenuOptionType.Footer; return item; } static buildOptionItem(id: number, title: string, displayText?: string, subDisplayText?: string): ISPClientAutoFillData { var item = {}; item[SPClientAutoFill.KeyProperty] = id; item[SPClientAutoFill.DisplayTextProperty] = displayText || title; item[SPClientAutoFill.SubDisplayTextProperty] = subDisplayText; item[SPClientAutoFill.TitleTextProperty] = title; item[SPClientAutoFill.MenuOptionTypeProperty] = SPClientAutoFill.MenuOptionType.Option; return item; } static buildSeparatorItem(): ISPClientAutoFillData { var item = {}; item[SPClientAutoFill.MenuOptionTypeProperty] = SPClientAutoFill.MenuOptionType.Separator; return item; } static buildLoadingItem(title: string): ISPClientAutoFillData { var item = {}; item[SPClientAutoFill.MenuOptionTypeProperty] = SPClientAutoFill.MenuOptionType.Loading; item[SPClientAutoFill.DisplayTextProperty] = title; return item; } } /** Lightweight client-side rendering template overrides.*/ export interface ICSR { /** Override rendering template. @param name Name of template to override. @param template New template. */ template(name: string, template: string): ICSR; /** Override rendering template. @param name Name of template to override. @param template New template. */ template(name: string, template: (ctx: SPClientTemplates.RenderContext) => string): ICSR; /** Override field rendering template. @param name Internal name of field to override. @param name Name of template to override. @param template New template. */ fieldTemplate(field: string, name: string, template: string): ICSR; /** Override field rendering template. @param name Internal name of field to override. @param name Name of template to override. @param template New template. */ fieldTemplate(field: string, name: string, template: (ctx: SPClientTemplates.RenderContext) => string): ICSR; /** Sets pre-render callbacks. Callback called before rendering starts. @param callbacks pre-render callbacks. */ onPreRender(...callbacks: { (ctx: SPClientTemplates.RenderContext): void; }[]): ICSR; /** Sets post-render callbacks. Callback called after rendered html inserted to DOM. @param callbacks post-render callbacks. */ onPostRender(...callbacks: { (ctx: SPClientTemplates.RenderContext): void; }[]): ICSR; /** Sets pre-render callbacks for field. Callback called before rendering starts. Correctly handles form rendering. @param fieldName Internal name of the field. @param callbacks pre-render callbacks. */ onPreRenderField(field: string, callback: { (schema: SPClientTemplates.FieldSchema, ctx: SPClientTemplates.RenderContext): void; }): ICSR; /** Sets post-render callbacks. Callback called after rendered html inserted to DOM. Correctly handles form rendering. @param fieldName Internal name of the field. @param callbacks post-render callbacks. */ onPostRenderField(field: string, callback: { (schema: SPClientTemplates.FieldSchema, ctx: SPClientTemplates.RenderContext): void; }): ICSR; /** Registers overrides in client-side templating engine.*/ register(): void; /** Override View rendering template. @param template New view template. */ view(template: string): ICSR; /** Override View rendering template. @param template New view template. */ view(template: (ctx: SPClientTemplates.RenderContext_InView) => string): ICSR; view(template: (ctx: SPClientTemplates.RenderContext_Form) => string): ICSR; /** Override Item rendering template. @param template New item template. */ item(template: string): ICSR; /** Override Item rendering template. @param template New item template. */ item(template: (ctx: SPClientTemplates.RenderContext_ItemInView) => string): ICSR; item(template: (ctx: SPClientTemplates.RenderContext_Form) => string): ICSR; /** Override Header rendering template. @param template New header template. */ header(template: string): ICSR; /** Override Header rendering template. @param template New header template. */ header(template: (ctx: SPClientTemplates.RenderContext) => string): ICSR; /** Override Body rendering template. @param template New body template. */ body(template: string): ICSR; /** Override Body rendering template. @param template New body template. */ body(template: (ctx: SPClientTemplates.RenderContext) => string): ICSR; /** Override Footer rendering template. @param template New footer template. */ footer(template: string): ICSR; /** Override Footer rendering template. @param template New footer template. */ footer(template: (ctx: SPClientTemplates.RenderContext) => string): ICSR; /** Override View rendering template for specified field. @param fieldName Internal name of the field. @param template New View template. */ fieldView(fieldName: string, template: string): ICSR; /** Override View rendering template for specified field. @param fieldName Internal name of the field. @param template New View template. */ fieldView(fieldName: string, template: (ctx: SPClientTemplates.RenderContext_FieldInView) => string): ICSR; /** Override DisplyForm rendering template for specified field. @param fieldName Internal name of the field. @param template New DisplyForm template. */ fieldDisplay(fieldName: string, template: string): ICSR; /** Override DisplyForm rendering template. @param fieldName Internal name of the field. @param template New DisplyForm template. */ fieldDisplay(fieldName: string, template: (ctx: SPClientTemplates.RenderContext_FieldInForm) => string): ICSR; /** Override EditForm rendering template for specified field. @param fieldName Internal name of the field. @param template New EditForm template. */ fieldEdit(fieldName: string, template: string): ICSR; /** Override EditForm rendering template. @param fieldName Internal name of the field. @param template New EditForm template. */ fieldEdit(fieldName: string, template: (ctx: SPClientTemplates.RenderContext_FieldInForm) => string): ICSR; /** Override NewForm rendering template for specified field. @param fieldName Internal name of the field. @param template New NewForm template. */ fieldNew(fieldName: string, template: string): ICSR; /** Override NewForm rendering template. @param fieldName Internal name of the field. @param template New NewForm template. */ fieldNew(fieldName: string, template: (ctx: SPClientTemplates.RenderContext_FieldInForm) => string): ICSR; /** Set initial value for field. @param fieldName Internal name of the field. @param value Initial value for field. */ setInitialValue(fieldName: string, value: any): ICSR; /** Make field hidden in list view and standard forms. @param fieldName Internal name of the field. */ makeHidden(fieldName: string): ICSR /** Replace New and Edit templates for field to Display template. @param fieldName Internal name of the field. */ makeReadOnly(fieldName: string): ICSR /** Create cascaded Lookup Field. @param fieldName Internal name of the field. @param camlFilter CAML predicate expression (inside Where clause). Use {FieldName} tokens for dependency fields substitutions. */ filteredLookup(fieldName: string, camlFilter: string, listname?: string, lookupField?: string): ICSR /** Auto computes text-based field value based on another fields. @param targetField Internal name of the field. @param transform Function combines source field values. @param sourceField Internal names of source fields. */ computedValue(targetField: string, transform: (...values: string[]) => string, ...sourceField: string[]): ICSR /** Field text value with autocomplete based on autofill.js @param fieldName Internal name of the field. @param ctx AutoFill context. */ autofill(fieldName: string, init: (ctx: IAutoFillFieldContext) => () => void): ICSR /** Replace defult dropdown to search-based autocomplete for Lookup field. @param fieldName Internal name of the field. */ seachLookup(fieldName: string): ICSR; /** Adds link to add new value to lookup list. @param fieldName Internal name of the field. @param prompt Text to display as a link to add new value. @param contentTypeID Default content type for new item. */ lookupAddNew(fieldName: string, prompt: string, showDialog?: boolean, contentTypeId?: string): ICSR; koEditField(fieldName: string, template: string, vm: IKoFieldInForm, dependencyFields?: string[]): ICSR; } export interface IAutoFillFieldContext { renderContext: SPClientTemplates.RenderContext_FieldInForm; fieldContext: SPClientTemplates.ClientFormContext; autofill: SPClientAutoFill; control: HTMLInputElement; } export interface IKoFieldInForm { renderingContext?:SPClientTemplates.RenderContext_FieldInForm; value?:KnockoutObservable; } interface IFormRenderContexWithHook extends SPClientTemplates.RenderContext_FieldInForm { FormContextHook: IFormContextHook; } interface IFormContextHook { [fieldName: string]: IFormContextHookField; } interface IFormContextHookField { fieldSchema?: SPClientTemplates.FieldSchema_InForm; lastValue?: any; getValue?: () => any; updatedValueCallbacks: UpdatedValueCallback[]; } function ensureFormContextHookField(hook: IFormContextHook, fieldName: string): IFormContextHookField { return hook[fieldName] = hook[fieldName] || { updatedValueCallbacks: [] }; } class BooleanValueValidator implements SPClientForms.ClientValidation.IValidator { constructor(public valueGetter: () => boolean, public validationMessage: string) { } Validate(value: any): SPClientForms.ClientValidation.ValidationResult { return new SPClientForms.ClientValidation.ValidationResult(!this.valueGetter(), this.validationMessage); } } } if (typeof SP == 'object' && SP && typeof SP.SOD == 'object' && SP.SOD) { SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs("typescripttemplates.ts"); } //mquery.ts module spdevlab { export module mQuery { export class DynamicTable { // private fields _domContainer:HTMLElement; _tableContainer:MQueryResultSetElements; _rowTemplateId:string = null; _rowTemplateContent:string = null; _options = { tableCnt: '.spdev-rep-tb', addCnt: '.spdev-rep-tb-add', removeCnt: '.spdev-rep-tb-del' }; // public methods init(domContainer: HTMLElement, options) { if (m$.isDefinedAndNotNull(options)) { m$.extend(this._options, options); } this._initContainers(domContainer); this._initRowTemplate(); this._initEvents(); this._showUI(); } // private methods _initContainers(domContainer) { this._domContainer = domContainer; this._tableContainer = m$(this._options.tableCnt, this._domContainer); } _showUI() { m$(this._domContainer).css("display", ""); } _initEvents() { m$(this._options.addCnt, this._domContainer).click(() => { if (m$.isDefinedAndNotNull(this._rowTemplateContent)) { m$(this._tableContainer).append(this._rowTemplateContent); m$("tr:last-child " + this._options.removeCnt, this._tableContainer).click( (e) => { var targetElement = e.currentTarget; var parentRow = m$(targetElement).parents("tr").first(); m$(parentRow).remove(); }); } return false; }); } _initRowTemplate() { var templateId = m$(this._tableContainer).attr("template-id"); if (m$.isDefinedAndNotNull(templateId)) { this._rowTemplateId = templateId; this._rowTemplateContent = DynamicTable._templates[templateId]; } } static _templates:string[] = []; static initTables() { // init templates m$('script').forEach((template:HTMLElement) => { var id = m$(template).attr("dynamic-table-template-id"); if (m$.isDefinedAndNotNull(id)) { DynamicTable._templates[id] = template.innerHTML; } }); // init tables m$(".spdev-rep-tb-cnt").forEach( divContainer => { var dynamicTable = new DynamicTable(); dynamicTable.init(divContainer, { removeCnt: '.spdev-rep-tb-del-override' }); }); } }; } } m$.ready(() => { spdevlab.mQuery.DynamicTable.initTables(); }); //whoisapppart.ts module _ { var queryString = parseQueryString(); var isIframe = queryString['DisplayMode'] == 'iframe' var spHostUrl = queryString['SPHostUrl']; var editmode = Number(queryString['editmode']); var includeDetails = queryString['boolProp'] == 'true'; prepareVisual(); m$.ready(() => { loadPeoplePicker('peoplePicker'); partProperties(); if (isIframe) { partResize(); } }); //Load the people picker function loadPeoplePicker(peoplePickerElementId: string) { var schema: ISPClientPeoplePickerSchema = { PrincipalAccountType: "User", AllowMultipleValues: false, Width: 300, OnUserResolvedClientScript: onUserResolvedClientScript } SPClientPeoplePicker.InitializeStandalonePeoplePicker(peoplePickerElementId, null, schema); } function onUserResolvedClientScript(el: string, users: ISPClientPeoplePickerEntity[]) { if (users.length > 0) { var person = users[0]; var accountName = person.Key; var context = SP.ClientContext.get_current(); var peopleManager = new SP.UserProfiles.PeopleManager(context); var personProperties = peopleManager.getPropertiesFor(accountName); context.load(personProperties); context.executeQueryAsync((sender, args) => { $get("basicInfo").style.display = 'block'; var userPic = personProperties.get_userProfileProperties()["PictureURL"]; $get("pic").innerHTML = ' + personProperties.get_displayName() + '; $get("name").innerHTML = '' + personProperties.get_displayName() + ''; $get("email").innerHTML = '' + personProperties.get_email() + ''; $get("title").innerHTML = personProperties.get_title(); $get("department").innerHTML = person.EntityData.Department; $get("phone").innerHTML = person.EntityData.MobilePhone; var properties = personProperties.get_userProfileProperties(); var messageText = ""; for (var key in properties) { messageText += "
[" + key + "]: \"" + properties[key] + "\""; } $get("detailInfo").innerHTML = messageText; if (isIframe) { partResize(); } }, (sender, args) => { alert('Error: ' + args.get_message()); }); } } function partProperties() { if (editmode == 1) { $get("editmodehdr").style.display = "inline"; $get("content").style.display = "none"; } else if (includeDetails) { $get('detailInfo').style.display = 'block'; $get("editmodehdr").style.display = "none"; $get("content").style.display = "inline"; } } function partResize() { var bounds = Sys.UI.DomElement.getBounds(document.body); parent.postMessage('resize(' + bounds.width + ',' + bounds.height + ')', '*'); } function prepareVisual() { if (isIframe) { //Create a Link element for the defaultcss.ashx resource var linkElement = document.createElement('link'); linkElement.setAttribute('rel', 'stylesheet'); linkElement.setAttribute('href', spHostUrl + '/_layouts/15/defaultcss.ashx'); //Add the linkElement as a child to the head section of the html document.head.appendChild(linkElement); } else { m$.ready(() => { var nav = new SP.UI.Controls.Navigation('navigation', { appIconUrl: queryString['SPHostLogo'], appTitle: document.title }); nav.setVisible(true); $get('apppart-notification').style.display = 'block'; document.body.style.overflow = 'visible'; }); } } function parseQueryString() { var result = {}; var qs = document.location.search.split('?')[1]; if (qs) { var parts = qs.split('&'); for (var i = 0; i < parts.length; i++) { if (parts[i]) { var pair = parts[i].split('='); result[pair[0]] = decodeURIComponent(pair[1]); } } } return result; } } //taxonomy module SP { // Class export class ClientContextPromise extends SP.ClientContext { /** To use this function, you must ensure that jQuery and CSOMPromise js files are loaded to the page */ executeQueryPromise(): JQueryPromise { var deferred = jQuery.Deferred(); this.executeQueryAsync(function (sender, args) { deferred.resolve(sender, args); }, function (sender, args) { deferred.reject(sender, args); }) return deferred.promise(); } constructor(serverRelativeUrlOrFullUrl: string) { super(serverRelativeUrlOrFullUrl); } static get_current(): ClientContextPromise { return new ClientContextPromise(_spPageContextInfo.siteServerRelativeUrl); } } } SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs("CSOMPromise.ts"); module _ { var context: SP.ClientContextPromise; var web: SP.Web; var site: SP.Site; var session: SP.Taxonomy.TaxonomySession; var termStore: SP.Taxonomy.TermStore; var groups: SP.Taxonomy.TermGroupCollection; // This code runs when the DOM is ready and creates a context object // which is needed to use the SharePoint object model. // It also wires up the click handlers for the two HTML buttons in Default.aspx. $(document).ready(function () { context = SP.ClientContextPromise.get_current(); site = context.get_site(); web = context.get_web(); $('#listExisting').click(function () { listGroups(); }); $('#createTerms').click(function () { createTerms(); }); }); // When the listExisting button is clicked, start by loading // a TaxonomySession for the current context. Also get and load // the associated term store. function listGroups() { session = SP.Taxonomy.TaxonomySession.getTaxonomySession(context); termStore = session.getDefaultSiteCollectionTermStore(); context.load(session); context.load(termStore); context.executeQueryAsync(onListTaxonomySession, onFailListTaxonomySession); } // Runs when the executeQueryAsync method in the listGroups function has succeeded. // In this case, get and load the groups associated with the term store that we // know we now have a reference to. function onListTaxonomySession() { groups = termStore.get_groups(); context.load(groups); context.executeQueryAsync(onRetrieveGroups, onFailRetrieveGroups); } // Runs when the executeQueryAsync method in the onListTaxonomySession function has succeeded. // In this case, loop through all the groups and add a clickable div element to the report area // for each group. // NOTE: We clear the report area first to ensure we have a clean place to write to. // Also note how we create a click event handler for each div on-the-fly, and that we pass in the // current group ID to that function. So when the user clicks one of these divs, we will know which // one was clicked. function onRetrieveGroups() { $('#report').children().remove(); var groupEnum = groups.getEnumerator(); // For each group, we'll build a clickable div. while (groupEnum.moveNext()) { (() => { var currentGroup = groupEnum.get_current(); var groupName = document.createElement("div"); groupName.setAttribute("style", "float:none;cursor:pointer"); var groupID = currentGroup.get_id(); groupName.setAttribute("id", groupID.toString()); $(groupName).click(() => showTermSets(groupID)); groupName.appendChild(document.createTextNode(currentGroup.get_name())); $('#report').append(groupName); })(); } } // This is the function that runs when the user clicks one of the divs // that we created in the onRetrieveGroups function. We can know which // div was clicked by interrogating the groupID parameter. So what we'll // do is retrieve a reference to the group with the same ID as the div, and // then add the term sets that belong to that group under the div that was clicked. function showTermSets(groupID: SP.Guid) { // First thing is to remnove the divs under the group DIV to ensure we have a clean place to write to. // The reason we don't clear them all is becuase we want to retain the text node of the // group div. I.E. that's why we use "parentDiv.childNodes.length>1" as our loop // controller. var parentDiv = document.getElementById(groupID.toString()); while (parentDiv.childNodes.length > 1) { parentDiv.removeChild(parentDiv.lastChild); } // For each term set, we'll build a clickable div var currentGroup = groups.getById(groupID); // We need to load and populate the matching group first, or the // term sets that it contains will be inaccessible to our code. context.load(currentGroup); var termSets: SP.Taxonomy.TermSetCollection; context.executeQueryPromise() .then( () => { // The group is now available becuase this is the // success callback. So now we'll load and populate the // term set collection. We have to do this before we can // iterate through the collection, so we can do this // with the following nested executeQueryAsync method call. termSets = currentGroup.get_termSets(); context.load(termSets); return context.executeQueryPromise() }) .then(() => { // The term sets are now available becuase this is the // success callback. So now we'll iterate through the collection // and create the clickable div. Also note how we create a // click event handler for each div on-the-fly, and that we pass in the // current group ID and term set ID to that function. So when the user // clicks one of these divs, we will know which // one was clicked by its term set ID, and to which group it belongs by its // group ID. We also pass in the event object, so that we can cancel the bubble // because this clickable div will be inside a parent clickable div and we // don't want the parent's event to fire. var termSetEnum = termSets.getEnumerator(); while (termSetEnum.moveNext()) { (() => { var currentTermSet = termSetEnum.get_current(); var termSetName = document.createElement("div"); termSetName.appendChild(document.createTextNode(" + " + currentTermSet.get_name())); termSetName.setAttribute("style", "float:none;cursor:pointer;"); var termSetID = currentTermSet.get_id(); termSetName.setAttribute("id", termSetID.toString()); $(termSetName).click(e => showTerms(e, groupID, termSetID)); parentDiv.appendChild(termSetName); })(); } }) .fail(() => parentDiv.appendChild(document.createTextNode("An error occurred in loading the term sets for this group"))); } // This is the function that runs when the user clicks one of the divs // that we created in the showTermSets function. We can know which // div was clicked by interrogating the termSetID parameter. So what we'll // do is retrieve a reference to the term set with the same ID as the div, and // then add the term that belong to that term set under the div that was clicked. function showTerms(event: JQueryEventObject, groupID: SP.Guid, termSetID: SP.Guid) { // First, cancel the bubble so that the group div click handler does not also fire // because that removes all term set divs and we don't want that here. event.cancelBubble = true; // Get a reference to the term set div that was click and // remove its children (apart from the TextNode that is currently // showing the term set name. var parentDiv = document.getElementById(termSetID.toString()); while (parentDiv.childNodes.length > 1) { parentDiv.removeChild(parentDiv.lastChild); } // We need to load and populate the matching group first, or the // term sets that it contains will be inaccessible to our code. var currentGroup = groups.getById(groupID); var termSets:SP.Taxonomy.TermSetCollection; var currentTermSet:SP.Taxonomy.TermSet; var terms:SP.Taxonomy.TermCollection; context.load(currentGroup); context .executeQueryPromise() .then(() => { // The group is now available becuase this is the // success callback. So now we'll load and populate the // term set collection. We have to do this before we can // iterate through the collection, so we can do this // with the following nested executeQueryAsync method call. termSets = currentGroup.get_termSets(); context.load(termSets); return context.executeQueryPromise(); }) .then(() => { currentTermSet = termSets.getById(termSetID); context.load(currentTermSet); return context.executeQueryPromise(); }) .then(() => { terms = currentTermSet.get_terms(); context.load(terms); return context.executeQueryPromise(); }) .then(() => { var termsEnum = terms.getEnumerator(); while (termsEnum.moveNext()) { var currentTerm = termsEnum.get_current(); var term = document.createElement("div"); term.appendChild(document.createTextNode(" - " + currentTerm.get_name())); term.setAttribute("style", "float:none;margin-left:10px;"); parentDiv.appendChild(term); } }) .fail(() => parentDiv.appendChild(document.createTextNode("An error occurred when trying to retrieve terms in this term set"))); } // Runs when the executeQueryAsync method in the onListTaxonomySession function has failed. // In this case, clear the report area in the page and tell the user what went wrong. function onFailRetrieveGroups(sender, args) { $('#report').children().remove(); $('#report').append("Failed to retrieve groups. Error:" + args.get_message()); } // Runs when the executeQueryAsync method in the listGroups function has failed. // In this case, clear the report area in the page and tell the user what went wrong. function onFailListTaxonomySession(sender, args) { $('#report').children().remove(); $('#report').append("Failed to get session. Error: " + args.get_message()); } // When the createTerms button is clicked, start by loading // a TaxonomySession for the current context. Also get and load // the associated term store. function createTerms() { session = SP.Taxonomy.TaxonomySession.getTaxonomySession(context); termStore = session.getDefaultSiteCollectionTermStore(); context.load(session); context.load(termStore); context.executeQueryAsync(onGetTaxonomySession, onFailTaxonomySession); } // This function is the success callback for loading the session and store from the createTerms function function onGetTaxonomySession() { // Create six GUIDs that we will need when we create a new group, term set, and associated terms var guidGroupValue = SP.Guid.newGuid(); var guidTermSetValue = SP.Guid.newGuid(); var guidTerm1 = SP.Guid.newGuid(); var guidTerm2 = SP.Guid.newGuid(); var guidTerm3 = SP.Guid.newGuid(); var guidTerm4 = SP.Guid.newGuid(); // Create a new group var myGroup = termStore.createGroup("CustomTerms", guidGroupValue); // Create a new term set in the newly-created group var myTermSet = myGroup.createTermSet("Privacy", guidTermSetValue, 1033); // Create four new terms in the newly-created term set myTermSet.createTerm("Top Secret", 1033, guidTerm1); myTermSet.createTerm("Company Confidential", 1033, guidTerm2); myTermSet.createTerm("Partners Only", 1033, guidTerm3); myTermSet.createTerm("Public", 1033, guidTerm4); // Ensure the groups variable has been set, because when this all succeeds we will // effectively run the same code as if the user had clicked the listGroups button groups = termStore.get_groups(); context.load(groups); // Execute all the preceeding statements in this function context.executeQueryAsync(onAddTerms, onFailAddTerms); } // If all is well with creating the terms, then this function will run. // Effectively this runs the same code as if the user had clicked the listGroups button // so the user will see their newly-created group function onAddTerms() { listGroups(); } // Runs when the executeQueryAsync method in the onGetTaxonomySession function has failed. // In this case, clear the report area in the page and tell the user what went wrong. function onFailAddTerms(sender, args) { $('#report').children().remove(); $('#report').append("Failed to add terms. Error: " + args.get_message()); } // Runs when the executeQueryAsync method in the createTerms function has failed. // In this case, clear the report area in the page and tell the user what went wrong. function onFailTaxonomySession(sender, args) { $('#report').children().remove(); $('#report').append("Failed to get session. Error: " + args.get_message()); } }; //publishing.ts // Variables used in various callbacks JSRequest.EnsureSetup(); SP.SOD.execute('mquery.js', 'm$.ready', () => { var context = SP.ClientContext.get_current(); var web = context.get_web(); m$('#CreatePage').click(createPage); }); function createPage(evt) { SP.SOD.execute('sp.js', 'SP.ClientConext', () => { SP.SOD.execute('sp.publishing.js', 'SP.Publishing', () => { var context = SP.ClientContext.get_current(); var hostUrl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]); var hostcontext = new SP.AppContextSite(context, hostUrl); var web = hostcontext.get_web(); var pubWeb = SP.Publishing.PublishingWeb.getPublishingWeb(context, web); context.load(web); context.load(pubWeb); context.executeQueryAsync( // Success callback after getting the host Web as a PublishingWeb. // We now want to add a new Publishing Page. function () { var pageInfo = new SP.Publishing.PublishingPageInformation(); var newPage = pubWeb.addPublishingPage(pageInfo); context.load(newPage); context.executeQueryAsync( function () { // Success callback after adding a new Publishing Page. // We want to get the actual list item that is represented by the Publishing Page. var listItem = newPage.get_listItem(); context.load(listItem); context.executeQueryAsync( // Success callback after getting the actual list item that is // represented by the Publishing Page. // We can now get its FieldValues, one of which is its FileLeafRef value. // We can then use that value to build the Url to the new page // and set the href or our link to that Url. function () { var link = document.getElementById("linkToPage"); link.setAttribute("href", web.get_url() + "/Pages/" + listItem.get_fieldValues().FileLeafRef); link.innerText = "Go to new page!"; }, // Failure callback after getting the actual list item that is // represented by the Publishing Page. function (sender, args) { alert('Failed to get new page: ' + args.get_message()); } ); }, // Failure callback after trying to add a new Publishing Page. function (sender, args) { alert('Failed to Add Page: ' + args.get_message()); } ); }, // Failure callback after trying to get the host Web as a PublishingWeb. function (sender, args) { alert('Failed to get the PublishingWeb: ' + args.get_message()); } ); }); }); } //likes module SampleReputation { interface MyList extends SPClientTemplates.RenderContext_InView { listId: string; } class MyItem { id: number; title: string; likesCount: number; isLikedByCurrentUser: boolean; constructor(public row: SPClientTemplates.Item) { this.id = parseInt(row['ID']); this.title = row['Title']; this.likesCount = parseInt(row['LikesCount']) || 0; this.isLikedByCurrentUser = this.getLike(row['LikedBy']); } private getLike(likedBy): boolean { if (likedBy && likedBy.length > 0) { for (var i = 0; i < likedBy.length; i++) { if (likedBy[i].id == _spPageContextInfo.userId) { return true; } } } return false; } } function init() { SP.SOD.registerSod('reputation.js', '/_layouts/15/reputation.js'); SP.SOD.registerSod('typescripttemplates.ts', '/SPTypeScript/Extensions/typescripttemplates.js'); SP.SOD.executeFunc('typescripttemplates.ts', 'CSR', () => { CSR.override(10004, 1) .onPreRender((ctx: MyList) => { ctx.listId = ctx.listName.substring(1, 37); }) .header('
    ') .body(renderTemplate) .footer('
') .register(); }); SP.SOD.execute('mQuery.js', 'm$.ready', () => { RegisterModuleInit('/SPTypeScript/ReputationModule/likes.js', init); }); SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs('likes.js'); } function renderTemplate(ctx: MyList) { var rows = ctx.ListData.Row; var result = ''; for (var i = 0; i < rows.length; i++) { var item = new MyItem(rows[i]); result += '\
  • ' + item.title +'\ \ ' + getLikeText(item.isLikedByCurrentUser) + '' + item.likesCount + '\ \
  • '; } return result; } function getLikeText(isLikedByCurrentUser: boolean) { return isLikedByCurrentUser ? '\u2665' : '\u2661'; } export function setLike(itemId: number, listId: string): void { var context = SP.ClientContext.get_current(); var isLiked = m$('#likesCountText' + itemId)[0].textContent == '\u2661'; SP.SOD.executeFunc('reputation.js', 'Microsoft.Office.Server.ReputationModel.Reputation', function () { Microsoft.Office.Server.ReputationModel.Reputation.setLike(context, listId, itemId, isLiked); context.executeQueryAsync( () => { m$('#likesCountText' + itemId)[0].textContent = getLikeText(isLiked); var likesCount = parseInt(m$('#likesCount' + itemId)[0].textContent); m$('#likesCount' + itemId)[0].textContent = (isLiked ? likesCount + 1 : likesCount - 1).toString(); }, (sender, args) => { alert(args.get_message()); }); }); } init(); } //code from https://github.com/gandjustas/SharePointAngularTS module App { "use strict"; var app = angular.module("app", []); } // Install the angularjs.TypeScript.DefinitelyTyped NuGet package module App { "use strict"; interface Iappcontroller { title: string; activate: () => void; } class appcontroller implements Iappcontroller { title: string = "appcontroller"; lists: SP.List[]; static $inject: string[] = ["$SharePoint", "$spnotify"]; constructor(private $SharePoint: App.ISharePoint, private $n:App.ISpNotify) { this.activate(); } activate() { var loading = this.$n.showLoading(true) this.$SharePoint .getLists() .then(l => this.lists = l ) .catch((e: string) => this.$n.show(e, true)) .finally(() => this.$n.remove(loading) ); ; } } angular.module("app").controller("appcontroller", appcontroller); } module App { "use strict"; export interface ISharePoint { getLists: () => ng.IPromise; } class SharePointServcie implements ISharePoint { static $inject: string[] = ["$q"]; constructor(public $q: ng.IQService) { } getLists() { var promise = this.$q.defer(); SP.SOD.executeFunc("sp.js", "SP.ClientContext", () => { var ctx = SP.ClientContext.get_current(); var hostUrl = decodeURIComponent(SP.ScriptHelpers.getDocumentQueryPairs()['SPHostUrl']); var appCtx = new SP.AppContextSite(ctx, hostUrl); var hostWeb = appCtx.get_web(); var lists = hostWeb.get_lists(); ctx.load(lists); ctx.executeQueryAsync(() => { var result: SP.List[] = []; for (var e = lists.getEnumerator(); e.moveNext();) { result.push(e.get_current()); } promise.resolve(result); }, (o, args) => { promise.reject(args.get_message()); }); }); return promise.promise; } } angular.module("app").service("$SharePoint", SharePointServcie); } // Install the angularjs.TypeScript.DefinitelyTyped NuGet package module App { "use strict"; export interface ISpNotify { showLoading(sticky?: boolean) : string; show(msg: string, sticky?: boolean): string; remove(id: string):void; } class SpNotify implements ISpNotify { static $inject: string[] = []; showLoading(sticky: boolean = false) { return SP.UI.Notify.showLoadingNotification(sticky); } show(msg: string, sticky: boolean = false) { return SP.UI.Notify.addNotification(msg, sticky); } remove(id: string) { SP.UI.Notify.removeNotification(id); } } angular.module("app").service("$spnotify", SpNotify); }