parent
7b7a04ef6a
commit
87866b253c
|
@ -0,0 +1,25 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# we recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package,bower}.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -0,0 +1 @@
|
|||
* text=auto
|
|
@ -0,0 +1,32 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Visual Studio files
|
||||
.ntvs_analysis.dat
|
||||
.vs
|
||||
bin
|
||||
obj
|
||||
|
||||
# Resx Generated Code
|
||||
*.resx.ts
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
|
@ -0,0 +1,14 @@
|
|||
# Folders
|
||||
.vscode
|
||||
coverage
|
||||
node_modules
|
||||
sharepoint
|
||||
src
|
||||
temp
|
||||
|
||||
# Files
|
||||
*.csproj
|
||||
.git*
|
||||
.yo-rc.json
|
||||
gulpfile.js
|
||||
tsconfig.json
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"libraryName": "angular-search",
|
||||
"libraryId": "21c361d1-704f-4cf9-8756-967fa092bc81",
|
||||
"framework": "none"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
# Search Client-Side Web Part Built with Angular v1.x
|
||||
|
||||
## Summary
|
||||
Sample Search Web Part that illustrates how you can use Angular within the new SharePoint Framework
|
||||
|
||||
![Sample of the search web part](./assets/angularSearch.png)
|
||||
This app uses SharePoint's Search REST API endpoint to query listitems of a specific content type and displays the results to the end user.
|
||||
Ideally instead of selecting a content type for the search you would want to select a Result Source, but currently Result Sources are not
|
||||
available through SharePoint's REST API.
|
||||
|
||||
The logic for querying the SharePoint Content Types in the properties of the webpart was in part due to Chris O'Brien and this [blog post](http://www.sharepointnutsandbolts.com/2016/09/sharepoint-framework-spfx-web-part-properties-dynamic-dropdown.html?m=0)
|
||||
|
||||
> Note: In order to use the ngOfficeFabric code I use the ModuleLoader to load newer source files than the currently Office Fabric UI in SharePoint Online, which will cause many of the icons not to load properly on the SharePoint Page this webpart is added to.
|
||||
|
||||
> Note: For the display template of the search results I'm currently using the Office Fabric UI List template. Ideally I was hoping to use the DocumentCard Component, however, that is not yet available through the ngOfficUIFabric.
|
||||
|
||||
> Note: The List display is not currently displaying correctly because there appears to be an issue when loading https://appsforoffice.microsoft.com/fabric/2.6.1/fabric.components.min.css which causes the dropdowns in the property pane not to work.
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/drop-rc0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework Developer Preview](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
angular-search|David Hartman ([Slalom](https://slalom.com))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|February 4th, 2017|Initial release
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
||||
---
|
||||
|
||||
## Configuration Bliss
|
||||
|
||||
- clone this repo
|
||||
- in the command line run:
|
||||
- `npm i typings -g`
|
||||
- `npm i`
|
||||
- `gulp serve --nobrowser`
|
||||
- Enable the following features in you site
|
||||
- Publishing features on site collection
|
||||
- Publishing features on site
|
||||
|
||||
> Note: The Content Types that I pull for the search come from the Publishing Content Type which only
|
||||
> available when the Publishing Features are enabled on the site. I'm also searching by content type name
|
||||
> and not by id becauase then I would get everything that inherits from that content type. I only want the
|
||||
> the results for a specific content type and not everything that inherits that content type as well
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"entries": [
|
||||
{
|
||||
"entry": "./lib/webparts/angularSearch/AngularSearchWebPart.js",
|
||||
"manifest": "./src/webparts/angularSearch/AngularSearchWebPart.manifest.json",
|
||||
"outputPath": "./dist/angular-search.bundle.js"
|
||||
}
|
||||
],
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"angularSearchStrings": "webparts/angularSearch/loc/{locale}.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "angular-search",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"solution": {
|
||||
"name": "angular-search-client-side-solution",
|
||||
"id": "21c361d1-704f-4cf9-8756-967fa092bc81",
|
||||
"version": "1.0.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/angular-search.sppkg"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"port": 4321,
|
||||
"initialPage": "https://localhost:5432/workbench",
|
||||
"https": true,
|
||||
"api": {
|
||||
"port": 5432,
|
||||
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"label-undefined": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-case": true,
|
||||
"no-duplicate-key": false,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-imports": true,
|
||||
"no-unused-variable": true,
|
||||
"no-unreachable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false,
|
||||
"prefer-const": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.initialize(gulp);
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "angular-search",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-client-base": "~0.7.0",
|
||||
"@microsoft/sp-client-preview": "~0.9.0",
|
||||
"@microsoft/sp-core-library": "~0.1.2",
|
||||
"@microsoft/sp-webpart-base": "~0.4.0",
|
||||
"@types/angular": "^1.6.4",
|
||||
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||
"angular": "^1.5.10",
|
||||
"ng-office-ui-fabric": "^0.13.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~0.9.0",
|
||||
"@microsoft/sp-module-interfaces": "~0.7.0",
|
||||
"@microsoft/sp-webpart-workbench": "~0.8.0",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": ">=3.4.34 <3.6.0",
|
||||
"@types/mocha": ">=2.2.33 <2.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
var context = require.context('.', true, /.+\.test\.js?$/);
|
||||
|
||||
context.keys().forEach(context);
|
||||
|
||||
module.exports = context;
|
|
@ -0,0 +1,39 @@
|
|||
@import "~/office-ui-fabric-react/dist/sass/Fabric.Common";
|
||||
|
||||
.row {
|
||||
@include ms-Grid-row;
|
||||
@include ms-bgColor-themeDark;
|
||||
@include ms-fontColor-white;
|
||||
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-u-lg10;
|
||||
@include ms-u-xl8;
|
||||
@include ms-u-lgPush1;
|
||||
@include ms-u-xlPush2;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.button {
|
||||
text-decoration: none;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||
|
||||
"id": "23dc01e2-9059-49ff-9f2d-ba8edd5d1ee9",
|
||||
"alias": "AngularSearchWebPart",
|
||||
"componentType": "WebPart",
|
||||
"version": "0.0.1",
|
||||
"manifestVersion": 2,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "23dc01e2-9059-49ff-9f2d-ba8edd5d1ee9",
|
||||
"group": { "default": "Under Development" },
|
||||
"title": { "default": "AngularSearch" },
|
||||
"description": { "default": "AngularSearch description" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "AngularSearch",
|
||||
"contentTypes": ""
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
import {
|
||||
Version,
|
||||
Environment,
|
||||
EnvironmentType
|
||||
} from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField,
|
||||
IPropertyPaneDropdownOption,
|
||||
PropertyPaneDropdown,
|
||||
IWebPartContext
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
import { SPComponentLoader } from '@microsoft/sp-loader';
|
||||
import { SPHttpClient } from '@microsoft/sp-http';
|
||||
import { escape } from '@microsoft/sp-lodash-subset';
|
||||
|
||||
import styles from './AngularSearch.module.scss';
|
||||
import * as strings from 'angularSearchStrings';
|
||||
import { IAngularSearchWebPartProps } from './IAngularSearchWebPartProps';
|
||||
|
||||
import * as angular from 'angular';
|
||||
import MockHttpClient from './MockHttpClient';
|
||||
import './app/app.module';
|
||||
import 'ng-office-ui-fabric';
|
||||
|
||||
export interface ISPCTypeLists {
|
||||
value: ISPCType[];
|
||||
}
|
||||
|
||||
export interface ISPCType {
|
||||
Name: string;
|
||||
Description: string;
|
||||
Id: ISPStrVal;
|
||||
}
|
||||
|
||||
export interface ISPStrVal {
|
||||
StringValue: string;
|
||||
}
|
||||
|
||||
export default class AngularSearchWebPart extends BaseClientSideWebPart<IAngularSearchWebPartProps> {
|
||||
private $injector: angular.auto.IInjectorService;
|
||||
private _CTypesInThisSite: IPropertyPaneDropdownOption[] = [];
|
||||
|
||||
|
||||
public constructor(context: IWebPartContext) {
|
||||
super();
|
||||
|
||||
SPComponentLoader.loadCss('https://appsforoffice.microsoft.com/fabric/2.6.1/fabric.min.css');
|
||||
//SPComponentLoader.loadCss('https://appsforoffice.microsoft.com/fabric/2.6.1/fabric.components.min.css');
|
||||
}
|
||||
|
||||
public onInit<T>(): Promise<T> {
|
||||
//Determine if we are in a local environment
|
||||
if (Environment.type == EnvironmentType.Local) {
|
||||
this._getMockOptions().then((data) => {
|
||||
this._CTypesInThisSite = data;
|
||||
});
|
||||
}
|
||||
else {
|
||||
this._getOptions().then((data) => {
|
||||
this._CTypesInThisSite = data;
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
if (this.renderedOnce === false) {
|
||||
this.domElement.innerHTML = `<angularsearch web="${this.context.pageContext.web.absoluteUrl}" style='${angular.toJson(styles)}' contentType='${this.properties.contentTypes}'></angularsearch>`;
|
||||
this.$injector = angular.bootstrap(this.domElement, ['angularsearchapp']);
|
||||
}
|
||||
|
||||
this.$injector.get('$rootScope').$broadcast('configurationChanged', {
|
||||
contentType: this.properties.contentTypes
|
||||
});
|
||||
}
|
||||
|
||||
private _getCTypes(url: string): Promise<ISPCTypeLists> {
|
||||
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1).then((response: Response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
else {
|
||||
console.log("error: " + response.statusText);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _getMockOptions(): Promise<IPropertyPaneDropdownOption[]> {
|
||||
return this._getMockCTypes()
|
||||
.then((data: ISPCTypeLists) => {
|
||||
var options: Array<IPropertyPaneDropdownOption> = new Array<IPropertyPaneDropdownOption>();
|
||||
var cTypes: ISPCType[] = data.value;
|
||||
cTypes.forEach((cType: ISPCType) => {
|
||||
console.log("Found Content Type(s)");
|
||||
options.push({ key: cType.Id.StringValue, text: cType.Name });
|
||||
});
|
||||
|
||||
return options;
|
||||
});
|
||||
}
|
||||
|
||||
private _getMockCTypes(): Promise<ISPCTypeLists> {
|
||||
return MockHttpClient.get(this.context.pageContext.web.absoluteUrl)
|
||||
.then((data: ISPCType[]) => {
|
||||
let cTypeData: ISPCTypeLists = { value: data };
|
||||
return cTypeData;
|
||||
}) as Promise<ISPCTypeLists>;
|
||||
}
|
||||
|
||||
private _getOptions(): Promise<IPropertyPaneDropdownOption[]> {
|
||||
var url = this.context.pageContext.web.absoluteUrl + '/_api/web/AvailableContentTypes?$filter=Group eq \'Page Layout Content Types\'';
|
||||
|
||||
return this._getCTypes(url).then((response) => {
|
||||
var options: Array<IPropertyPaneDropdownOption> = new Array<IPropertyPaneDropdownOption>();
|
||||
var lists: ISPCType[] = response.value;
|
||||
lists.forEach((list: ISPCType) => {
|
||||
console.log("Found Content Type(s)");
|
||||
options.push({ key: list.Name, text: list.Name });
|
||||
});
|
||||
|
||||
return options;
|
||||
});
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('description', {
|
||||
label: strings.DescriptionFieldLabel
|
||||
}),
|
||||
PropertyPaneDropdown('contentTypes', {
|
||||
label: 'Available Content Types',
|
||||
options: this._CTypesInThisSite,
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export interface IAngularSearchWebPartProps {
|
||||
description: string;
|
||||
contentTypes: string;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { ISPCType } from './AngularSearchWebPart'
|
||||
|
||||
export default class MockHttpClient {
|
||||
private static _items: ISPCType[] = [
|
||||
{ Name: 'Mock CType 1', Description: 'Mock CType 1', Id: { StringValue: 'Mock CType 1' } },
|
||||
{ Name: 'Mock CType 2', Description: 'Mock CType 2', Id: { StringValue: 'Mock CType 2' } },
|
||||
{ Name: 'Mock CType 3', Description: 'Mock CType 3', Id: { StringValue: 'Mock CType 3' } }
|
||||
];
|
||||
|
||||
public static get(restUrl: string): Promise<ISPCType[]> {
|
||||
return new Promise<ISPCType[]>((resolve) => {
|
||||
resolve(MockHttpClient._items);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { ISearchResults } from './../models/ISearchResults'
|
||||
|
||||
export interface IDataService {
|
||||
getSearchResults(webUrl: string, contentType: string): angular.IPromise<ISearchResults>;
|
||||
}
|
||||
|
||||
export default class DataService implements IDataService {
|
||||
public static $inject: string[] = ['$q', '$http'];
|
||||
|
||||
constructor(private $q: angular.IQService, private $http: angular.IHttpService) { }
|
||||
|
||||
public getSearchResults(webUrl: string, contentType: string): angular.IPromise<ISearchResults> {
|
||||
const deferred: angular.IDeferred<ISearchResults> = this.$q.defer();
|
||||
|
||||
this.$http({
|
||||
url: `${webUrl}/_api/search/query?queryText='ContentType:"${contentType}"
|
||||
Path:${webUrl}'&selectproperties='Title,Author,HitHighlightedSummary,PublishingImage,Url'`,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json;odata=verbose'
|
||||
}
|
||||
}).then((response: angular.IHttpPromiseCallbackArg<any>): void => {
|
||||
if (response != null && response.data != null) {
|
||||
const result: ISearchResults = response.data.d.query;
|
||||
if (typeof result.PrimaryQueryResult !== 'undefined' &&
|
||||
typeof result.PrimaryQueryResult.RelevantResults !== 'undefined' &&
|
||||
typeof result.PrimaryQueryResult.RelevantResults.Table !== 'undefined' &&
|
||||
typeof result.PrimaryQueryResult.RelevantResults.Table.Rows !== 'undefined') {
|
||||
deferred.resolve(result);
|
||||
}
|
||||
else {
|
||||
deferred.reject("problem getting search results");
|
||||
}
|
||||
}
|
||||
else {
|
||||
deferred.reject("problem getting search results");
|
||||
}
|
||||
}, (error: any): void => {
|
||||
deferred.reject(error);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
import * as angular from 'angular';
|
||||
import { IDataService } from './DataService';
|
||||
import { ISearchResults, ICells, ICellValue } from './../models/ISearchResults';
|
||||
|
||||
interface IConfigurationChangeArgs {
|
||||
contentType: string;
|
||||
}
|
||||
|
||||
export default class HomeController {
|
||||
public static $inject: string[] = ['DataService', '$rootScope', '$scope', '$attrs'];
|
||||
|
||||
public status: string = undefined;
|
||||
public styles: any = null;
|
||||
public searchNotConfigured: boolean = true;
|
||||
public items: any[] = [];
|
||||
public searching: boolean = false;
|
||||
|
||||
private _web: string = null;
|
||||
private _contentType: string = undefined;
|
||||
|
||||
constructor(private dataService: IDataService, private $rootScope: angular.IRootScopeService, private $scope: angular.IScope, private $attrs: angular.IAttributes) {
|
||||
const vm: HomeController = this;
|
||||
|
||||
vm.styles = angular.fromJson($attrs['style']);
|
||||
vm._web = $attrs['web'];
|
||||
vm._contentType = $attrs['contenttype'] === "" ? undefined : $attrs['contenttype'];
|
||||
|
||||
if (this._contentType !== undefined) {
|
||||
this._init(this._contentType, vm.$scope);
|
||||
}
|
||||
else {
|
||||
this._init(undefined, undefined);
|
||||
}
|
||||
|
||||
$rootScope.$on('configurationChanged',
|
||||
(event: angular.IAngularEvent, args: IConfigurationChangeArgs): void => {
|
||||
vm._init(args.contentType, vm.$scope);
|
||||
});
|
||||
}
|
||||
|
||||
private _init(ctype: string, $scope: angular.IScope): void {
|
||||
if (ctype !== undefined && ctype.length > 0) {
|
||||
this._contentType = ctype;
|
||||
this.searchNotConfigured = false;
|
||||
}
|
||||
else {
|
||||
this.searchNotConfigured = true;
|
||||
}
|
||||
|
||||
this.status = this.searchNotConfigured ? 'Please select a contenet type in the Web Part properties' : 'Ready';
|
||||
if ($scope && this._contentType !== undefined) {
|
||||
//$scope.$digest();
|
||||
|
||||
//get search results as long as it isn't our mock dataService
|
||||
if (ctype.toLowerCase().indexOf('mock') == -1) {
|
||||
this.getSearchResults();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getSearchResults(): void {
|
||||
//display searching message
|
||||
this.searching = true;
|
||||
this.dataService.getSearchResults(this._web, this._contentType)
|
||||
.then((results: ISearchResults): void => {
|
||||
this.items = this._setSearchResults(results.PrimaryQueryResult.RelevantResults.Table.Rows.results);
|
||||
console.log(this.items);
|
||||
|
||||
//hide searching message
|
||||
this.searching = false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private _setSearchResults(searchResults: ICells[]): any[] {
|
||||
if (searchResults.length > 0) {
|
||||
const temp: any[] = [];
|
||||
searchResults.forEach((result: ICells) => {
|
||||
var val: Object = {};
|
||||
|
||||
result.Cells.results.forEach((cell: ICellValue) => {
|
||||
if (cell.Key == 'HitHighlightedSummary') {
|
||||
//need to replace <ddd> markup
|
||||
val[cell.Key] = cell.Value.replace(/ <ddd\/>/g, '.');
|
||||
}
|
||||
else if (cell.Key == 'PublishingImage' && cell.Value !== null) {
|
||||
//need to pull image url out of PublishingImage field
|
||||
let div = document.createElement('div');
|
||||
div.innerHTML = cell.Value;
|
||||
let img = div.getElementsByTagName('img')[0];
|
||||
val[cell.Key] = img.src;
|
||||
}
|
||||
else {
|
||||
val[cell.Key] = cell.Value;
|
||||
}
|
||||
});
|
||||
|
||||
temp.push(val);
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import * as angular from 'angular';
|
||||
import DataService from './DataService';
|
||||
import HomeController from './HomeController';
|
||||
|
||||
angular
|
||||
.module('angularsearchapp', [
|
||||
'officeuifabric.core',
|
||||
'officeuifabric.components'
|
||||
])
|
||||
.component('angularsearch', {
|
||||
controller: (HomeController),
|
||||
controllerAs: 'vm',
|
||||
bindings: {
|
||||
web: '@',
|
||||
style: '<',
|
||||
contentType: '@'
|
||||
},
|
||||
template: require(`home-template.html`).toString()
|
||||
})
|
||||
.service('DataService', DataService);
|
|
@ -0,0 +1,45 @@
|
|||
<div class="ms-Grid">
|
||||
<div class="">
|
||||
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white {{::vm.styles.row}}">
|
||||
<div class="ms-Grid-col ms-u-lg10 ms-u-x-18 ms-u-xlPush2 ms-u-lgPush1">
|
||||
<span class="ms-font-xl ms-fontColor-white">
|
||||
Sample SharePoint Search in Angular
|
||||
</span>
|
||||
<uif-button type="button" ng-click="vm.getSearchResults()" ng-disabled="vm.searchNotConfigured">
|
||||
<i class="ms-Icon ms-Icon--Sync" title="Refresh" aria-hidden="true"></i>
|
||||
</uif-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ms-Grid-row" ng-show="vm.searchNotConfigured">
|
||||
<div class="ms-Grid-col ms-u-sm12">
|
||||
{{vm.status}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ms-Grid-row" ng-show="vm.searching">
|
||||
<div class="ms-Grid-col ms-u-smPush6 ms-u-mdPush6 ms-u-lgPush6 ms-u-xlPush6">
|
||||
<uif-spinner uif-size="large">Searching...</uif-spinner>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ms-Grid-row">
|
||||
<div class="ms-Grid-col ms-u-sm-12">
|
||||
<div ng-show="!vm.searching">
|
||||
<uif-list uif-item-select-mode="single">
|
||||
<uif-list-item ng-repeat="item in vm.items" uif-item="item">
|
||||
<div class="ms-Grid-row">
|
||||
<div class="ms-Grid-col ms-u-sm-12">
|
||||
<uif-link ng-href="{{item.Url}}" style="text-decoration: none;">
|
||||
<uif-list-item-image>
|
||||
<img ng-src="{{item.PublishingImage}}" style="width: 80%" />
|
||||
</uif-list-item-image>
|
||||
<uif-list-item-primary-text>{{item.Title}}</uif-list-item-primary-text>
|
||||
<uif-list-item-secondary-text>By: {{item.Author}}</uif-list-item-secondary-text>
|
||||
<uif-list-item-tertiary-text>{{item.HitHighlightedSummary}}</uif-list-item-tertiary-text>
|
||||
</uif-link>
|
||||
</div>
|
||||
</div>
|
||||
</uif-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
declare interface IAngularSearchStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'angularSearchStrings' {
|
||||
const strings: IAngularSearchStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
export interface ISearchResults {
|
||||
PrimaryQueryResult: IPrimaryQueryResult;
|
||||
}
|
||||
|
||||
export interface IPrimaryQueryResult {
|
||||
RelevantResults: IRelevantResults;
|
||||
}
|
||||
|
||||
export interface IRelevantResults {
|
||||
Table: ITable;
|
||||
}
|
||||
|
||||
export interface ITable {
|
||||
Rows: IResults;
|
||||
}
|
||||
|
||||
export interface IResults {
|
||||
results: Array<ICells>;
|
||||
}
|
||||
|
||||
export interface ICells {
|
||||
Cells: IResultValues;
|
||||
}
|
||||
|
||||
export interface IResultValues {
|
||||
results: Array<ICellValue>;
|
||||
}
|
||||
|
||||
export interface ICellValue {
|
||||
Key: string;
|
||||
Value: string;
|
||||
ValueType: string;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/// <reference types="mocha" />
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
describe('AngularSearchWebPart', () => {
|
||||
it('should do something', () => {
|
||||
assert.ok(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"types": [
|
||||
"webpack-env"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// Type definitions for Microsoft ODSP projects
|
||||
// Project: ODSP
|
||||
|
||||
/* Global definition for UNIT_TEST builds */
|
||||
declare const UNIT_TEST: boolean;
|
|
@ -0,0 +1,15 @@
|
|||
// Type definitions for assertion-error 1.0.0
|
||||
// Project: https://github.com/chaijs/assertion-error
|
||||
// Definitions by: Bart van der Schoor <https://github.com/Bartvds>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
declare module 'assertion-error' {
|
||||
class AssertionError implements Error {
|
||||
constructor(message: string, props?: any, ssf?: Function);
|
||||
name: string;
|
||||
message: string;
|
||||
showDiff: boolean;
|
||||
stack: string;
|
||||
}
|
||||
export = AssertionError;
|
||||
}
|
|
@ -0,0 +1,631 @@
|
|||
// Type definitions for Knockout v3.2.0
|
||||
// Project: http://knockoutjs.com
|
||||
// Definitions by: Boris Yankov <https://github.com/borisyankov/>, Igor Oleinikov <https://github.com/Igorbek/>, Clément Bourgeois <https://github.com/moonpyk/>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
|
||||
interface KnockoutSubscribableFunctions<T> {
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
|
||||
notifySubscribers(valueToWrite?: T, event?: string): void;
|
||||
}
|
||||
|
||||
interface KnockoutComputedFunctions<T> {
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
}
|
||||
|
||||
interface KnockoutObservableFunctions<T> {
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
|
||||
equalityComparer(a: any, b: any): boolean;
|
||||
}
|
||||
|
||||
interface KnockoutObservableArrayFunctions<T> {
|
||||
// General Array functions
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
slice(start: number, end?: number): T[];
|
||||
splice(start: number): T[];
|
||||
splice(start: number, deleteCount: number, ...items: T[]): T[];
|
||||
pop(): T;
|
||||
push(...items: T[]): void;
|
||||
shift(): T;
|
||||
unshift(...items: T[]): number;
|
||||
reverse(): KnockoutObservableArray<T>;
|
||||
sort(): KnockoutObservableArray<T>;
|
||||
sort(compareFunction: (left: T, right: T) => number): KnockoutObservableArray<T>;
|
||||
|
||||
// Ko specific
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
|
||||
replace(oldItem: T, newItem: T): void;
|
||||
|
||||
remove(item: T): T[];
|
||||
remove(removeFunction: (item: T) => boolean): T[];
|
||||
removeAll(items: T[]): T[];
|
||||
removeAll(): T[];
|
||||
|
||||
destroy(item: T): void;
|
||||
destroy(destroyFunction: (item: T) => boolean): void;
|
||||
destroyAll(items: T[]): void;
|
||||
destroyAll(): void;
|
||||
}
|
||||
|
||||
interface KnockoutSubscribableStatic {
|
||||
fn: KnockoutSubscribableFunctions<any>;
|
||||
|
||||
new <T>(): KnockoutSubscribable<T>;
|
||||
}
|
||||
|
||||
interface KnockoutSubscription {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
interface KnockoutSubscribable<T> extends KnockoutSubscribableFunctions<T> {
|
||||
subscribe(callback: (newValue: T) => void, target?: any, event?: string): KnockoutSubscription;
|
||||
subscribe<TEvent>(callback: (newValue: TEvent) => void, target: any, event: string): KnockoutSubscription;
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutSubscribable<T>;
|
||||
getSubscriptionsCount(): number;
|
||||
}
|
||||
|
||||
interface KnockoutComputedStatic {
|
||||
fn: KnockoutComputedFunctions<any>;
|
||||
|
||||
<T>(): KnockoutComputed<T>;
|
||||
<T>(func: () => T, context?: any, options?: any): KnockoutComputed<T>;
|
||||
<T>(def: KnockoutComputedDefine<T>, context?: any): KnockoutComputed<T>;
|
||||
}
|
||||
|
||||
interface KnockoutComputed<T> extends KnockoutObservable<T>, KnockoutComputedFunctions<T> {
|
||||
fn: KnockoutComputedFunctions<any>;
|
||||
|
||||
dispose(): void;
|
||||
isActive(): boolean;
|
||||
getDependenciesCount(): number;
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutComputed<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservableArrayStatic {
|
||||
fn: KnockoutObservableArrayFunctions<any>;
|
||||
|
||||
<T>(value?: T[]): KnockoutObservableArray<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservableArray<T> extends KnockoutObservable<T[]>, KnockoutObservableArrayFunctions<T> {
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutObservableArray<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservableStatic {
|
||||
fn: KnockoutObservableFunctions<any>;
|
||||
|
||||
<T>(value?: T): KnockoutObservable<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservable<T> extends KnockoutSubscribable<T>, KnockoutObservableFunctions<T> {
|
||||
(): T;
|
||||
(value: T): void;
|
||||
|
||||
peek(): T;
|
||||
valueHasMutated?:{(): void;};
|
||||
valueWillMutate?:{(): void;};
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutObservable<T>;
|
||||
}
|
||||
|
||||
interface KnockoutComputedDefine<T> {
|
||||
read(): T;
|
||||
write? (value: T): void;
|
||||
disposeWhenNodeIsRemoved?: Node;
|
||||
disposeWhen? (): boolean;
|
||||
owner?: any;
|
||||
deferEvaluation?: boolean;
|
||||
pure?: boolean;
|
||||
}
|
||||
|
||||
interface KnockoutBindingContext {
|
||||
$parent: any;
|
||||
$parents: any[];
|
||||
$root: any;
|
||||
$data: any;
|
||||
$rawData: any | KnockoutObservable<any>;
|
||||
$index?: KnockoutObservable<number>;
|
||||
$parentContext?: KnockoutBindingContext;
|
||||
$component: any;
|
||||
$componentTemplateNodes: Node[];
|
||||
|
||||
extend(properties: any): any;
|
||||
createChildContext(dataItemOrAccessor: any, dataItemAlias?: any, extendCallback?: Function): any;
|
||||
}
|
||||
|
||||
interface KnockoutAllBindingsAccessor {
|
||||
(): any;
|
||||
get(name: string): any;
|
||||
has(name: string): boolean;
|
||||
}
|
||||
|
||||
interface KnockoutBindingHandler {
|
||||
after?: Array<string>;
|
||||
init?: (element: any, valueAccessor: () => any, allBindingsAccessor?: KnockoutAllBindingsAccessor, viewModel?: any, bindingContext?: KnockoutBindingContext) => void | { controlsDescendantBindings: boolean; };
|
||||
update?: (element: any, valueAccessor: () => any, allBindingsAccessor?: KnockoutAllBindingsAccessor, viewModel?: any, bindingContext?: KnockoutBindingContext) => void;
|
||||
options?: any;
|
||||
preprocess?: (value: string, name: string, addBindingCallback?: (name: string, value: string) => void) => string;
|
||||
}
|
||||
|
||||
interface KnockoutBindingHandlers {
|
||||
[bindingHandler: string]: KnockoutBindingHandler;
|
||||
|
||||
// Controlling text and appearance
|
||||
visible: KnockoutBindingHandler;
|
||||
text: KnockoutBindingHandler;
|
||||
html: KnockoutBindingHandler;
|
||||
css: KnockoutBindingHandler;
|
||||
style: KnockoutBindingHandler;
|
||||
attr: KnockoutBindingHandler;
|
||||
|
||||
// Control Flow
|
||||
foreach: KnockoutBindingHandler;
|
||||
if: KnockoutBindingHandler;
|
||||
ifnot: KnockoutBindingHandler;
|
||||
with: KnockoutBindingHandler;
|
||||
|
||||
// Working with form fields
|
||||
click: KnockoutBindingHandler;
|
||||
event: KnockoutBindingHandler;
|
||||
submit: KnockoutBindingHandler;
|
||||
enable: KnockoutBindingHandler;
|
||||
disable: KnockoutBindingHandler;
|
||||
value: KnockoutBindingHandler;
|
||||
textInput: KnockoutBindingHandler;
|
||||
hasfocus: KnockoutBindingHandler;
|
||||
checked: KnockoutBindingHandler;
|
||||
options: KnockoutBindingHandler;
|
||||
selectedOptions: KnockoutBindingHandler;
|
||||
uniqueName: KnockoutBindingHandler;
|
||||
|
||||
// Rendering templates
|
||||
template: KnockoutBindingHandler;
|
||||
|
||||
// Components (new for v3.2)
|
||||
component: KnockoutBindingHandler;
|
||||
}
|
||||
|
||||
interface KnockoutMemoization {
|
||||
memoize(callback: () => string): string;
|
||||
unmemoize(memoId: string, callbackParams: any[]): boolean;
|
||||
unmemoizeDomNodeAndDescendants(domNode: any, extraCallbackParamsArray: any[]): boolean;
|
||||
parseMemoText(memoText: string): string;
|
||||
}
|
||||
|
||||
interface KnockoutVirtualElement {}
|
||||
|
||||
interface KnockoutVirtualElements {
|
||||
allowedBindings: { [bindingName: string]: boolean; };
|
||||
emptyNode(node: KnockoutVirtualElement ): void;
|
||||
firstChild(node: KnockoutVirtualElement ): KnockoutVirtualElement;
|
||||
insertAfter( container: KnockoutVirtualElement, nodeToInsert: Node, insertAfter: Node ): void;
|
||||
nextSibling(node: KnockoutVirtualElement): Node;
|
||||
prepend(node: KnockoutVirtualElement, toInsert: Node ): void;
|
||||
setDomNodeChildren(node: KnockoutVirtualElement, newChildren: { length: number;[index: number]: Node; } ): void;
|
||||
childNodes(node: KnockoutVirtualElement ): Node[];
|
||||
}
|
||||
|
||||
interface KnockoutExtenders {
|
||||
throttle(target: any, timeout: number): KnockoutComputed<any>;
|
||||
notify(target: any, notifyWhen: string): any;
|
||||
|
||||
rateLimit(target: any, timeout: number): any;
|
||||
rateLimit(target: any, options: { timeout: number; method?: string; }): any;
|
||||
|
||||
trackArrayChanges(target: any): any;
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE TO MAINTAINERS AND CONTRIBUTORS : pay attention to only include symbols that are
|
||||
// publicly exported in the minified version of ko, without that you can give the false
|
||||
// impression that some functions will be available in production builds.
|
||||
//
|
||||
interface KnockoutUtils {
|
||||
//////////////////////////////////
|
||||
// utils.domData.js
|
||||
//////////////////////////////////
|
||||
|
||||
domData: {
|
||||
get (node: Element, key: string): any;
|
||||
|
||||
set (node: Element, key: string, value: any): void;
|
||||
|
||||
getAll(node: Element, createIfNotFound: boolean): any;
|
||||
|
||||
clear(node: Element): boolean;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// utils.domNodeDisposal.js
|
||||
//////////////////////////////////
|
||||
|
||||
domNodeDisposal: {
|
||||
addDisposeCallback(node: Element, callback: Function): void;
|
||||
|
||||
removeDisposeCallback(node: Element, callback: Function): void;
|
||||
|
||||
cleanNode(node: Node): Element;
|
||||
|
||||
removeNode(node: Node): void;
|
||||
};
|
||||
|
||||
addOrRemoveItem<T>(array: T[] | KnockoutObservable<T>, value: T, included: T): void;
|
||||
|
||||
arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];
|
||||
|
||||
arrayFirst<T>(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T;
|
||||
|
||||
arrayForEach<T>(array: T[], action: (item: T, index: number) => void): void;
|
||||
|
||||
arrayGetDistinctValues<T>(array: T[]): T[];
|
||||
|
||||
arrayIndexOf<T>(array: T[], item: T): number;
|
||||
|
||||
arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];
|
||||
|
||||
arrayPushAll<T>(array: T[] | KnockoutObservableArray<T>, valuesToPush: T[]): T[];
|
||||
|
||||
arrayRemoveItem(array: any[], itemToRemove: any): void;
|
||||
|
||||
compareArrays<T>(a: T[], b: T[]): Array<KnockoutArrayChange<T>>;
|
||||
|
||||
extend(target: Object, source: Object): Object;
|
||||
|
||||
fieldsIncludedWithJsonPost: any[];
|
||||
|
||||
getFormFields(form: any, fieldName: string): any[];
|
||||
|
||||
objectForEach(obj: any, action: (key: any, value: any) => void): void;
|
||||
|
||||
parseHtmlFragment(html: string): any[];
|
||||
|
||||
parseJson(jsonString: string): any;
|
||||
|
||||
postJson(urlOrForm: any, data: any, options: any): void;
|
||||
|
||||
peekObservable<T>(value: KnockoutObservable<T>): T;
|
||||
|
||||
range(min: any, max: any): any;
|
||||
|
||||
registerEventHandler(element: any, eventType: any, handler: Function): void;
|
||||
|
||||
setHtml(node: Element, html: () => string): void;
|
||||
|
||||
setHtml(node: Element, html: string): void;
|
||||
|
||||
setTextContent(element: any, textContent: string | KnockoutObservable<string>): void;
|
||||
|
||||
stringifyJson(data: any, replacer?: Function, space?: string): string;
|
||||
|
||||
toggleDomNodeCssClass(node: any, className: string, shouldHaveClass: boolean): void;
|
||||
|
||||
triggerEvent(element: any, eventType: any): void;
|
||||
|
||||
unwrapObservable<T>(value: KnockoutObservable<T> | T): T;
|
||||
|
||||
// NOT PART OF THE MINIFIED API SURFACE (ONLY IN knockout-{version}.debug.js) https://github.com/SteveSanderson/knockout/issues/670
|
||||
// forceRefresh(node: any): void;
|
||||
// ieVersion: number;
|
||||
// isIe6: boolean;
|
||||
// isIe7: boolean;
|
||||
// jQueryHtmlParse(html: string): any[];
|
||||
// makeArray(arrayLikeObject: any): any[];
|
||||
// moveCleanedNodesToContainerElement(nodes: any[]): HTMLElement;
|
||||
// replaceDomNodes(nodeToReplaceOrNodeArray: any, newNodesArray: any[]): void;
|
||||
// setDomNodeChildren(domNode: any, childNodes: any[]): void;
|
||||
// setElementName(element: any, name: string): void;
|
||||
// setOptionNodeSelectionState(optionNode: any, isSelected: boolean): void;
|
||||
// simpleHtmlParse(html: string): any[];
|
||||
// stringStartsWith(str: string, startsWith: string): boolean;
|
||||
// stringTokenize(str: string, delimiter: string): string[];
|
||||
// stringTrim(str: string): string;
|
||||
// tagNameLower(element: any): string;
|
||||
}
|
||||
|
||||
interface KnockoutArrayChange<T> {
|
||||
status: string;
|
||||
value: T;
|
||||
index: number;
|
||||
moved?: number;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// templateSources.js
|
||||
//////////////////////////////////
|
||||
|
||||
interface KnockoutTemplateSourcesDomElement {
|
||||
text(): any;
|
||||
text(value: any): void;
|
||||
|
||||
data(key: string): any;
|
||||
data(key: string, value: any): any;
|
||||
}
|
||||
|
||||
interface KnockoutTemplateAnonymous extends KnockoutTemplateSourcesDomElement {
|
||||
nodes(): any;
|
||||
nodes(value: any): void;
|
||||
}
|
||||
|
||||
interface KnockoutTemplateSources {
|
||||
|
||||
domElement: {
|
||||
prototype: KnockoutTemplateSourcesDomElement
|
||||
new (element: Element): KnockoutTemplateSourcesDomElement
|
||||
};
|
||||
|
||||
anonymousTemplate: {
|
||||
prototype: KnockoutTemplateAnonymous;
|
||||
new (element: Element): KnockoutTemplateAnonymous;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// nativeTemplateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
interface KnockoutNativeTemplateEngine {
|
||||
|
||||
renderTemplateSource(templateSource: Object, bindingContext?: KnockoutBindingContext, options?: Object): any[];
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// templateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
interface KnockoutTemplateEngine extends KnockoutNativeTemplateEngine {
|
||||
|
||||
createJavaScriptEvaluatorBlock(script: string): string;
|
||||
|
||||
makeTemplateSource(template: any, templateDocument?: Document): any;
|
||||
|
||||
renderTemplate(template: any, bindingContext: KnockoutBindingContext, options: Object, templateDocument: Document): any;
|
||||
|
||||
isTemplateRewritten(template: any, templateDocument: Document): boolean;
|
||||
|
||||
rewriteTemplate(template: any, rewriterCallback: Function, templateDocument: Document): void;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
interface KnockoutStatic {
|
||||
utils: KnockoutUtils;
|
||||
memoization: KnockoutMemoization;
|
||||
|
||||
bindingHandlers: KnockoutBindingHandlers;
|
||||
getBindingHandler(handler: string): KnockoutBindingHandler;
|
||||
|
||||
virtualElements: KnockoutVirtualElements;
|
||||
extenders: KnockoutExtenders;
|
||||
|
||||
applyBindings(viewModelOrBindingContext?: any, rootNode?: any): void;
|
||||
applyBindingsToDescendants(viewModelOrBindingContext: any, rootNode: any): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: (bindingContext: KnockoutBindingContext, node: Node) => {}, bindingContext: KnockoutBindingContext): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: {}, bindingContext: KnockoutBindingContext): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: (bindingContext: KnockoutBindingContext, node: Node) => {}, viewModel: any): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: {}, viewModel: any): void;
|
||||
applyBindingsToNode(node: Node, bindings: any, viewModelOrBindingContext?: any): any;
|
||||
|
||||
subscribable: KnockoutSubscribableStatic;
|
||||
observable: KnockoutObservableStatic;
|
||||
|
||||
computed: KnockoutComputedStatic;
|
||||
pureComputed<T>(evaluatorFunction: () => T, context?: any): KnockoutComputed<T>;
|
||||
pureComputed<T>(options: KnockoutComputedDefine<T>, context?: any): KnockoutComputed<T>;
|
||||
|
||||
observableArray: KnockoutObservableArrayStatic;
|
||||
|
||||
contextFor(node: any): any;
|
||||
isSubscribable(instance: any): boolean;
|
||||
toJSON(viewModel: any, replacer?: Function, space?: any): string;
|
||||
toJS(viewModel: any): any;
|
||||
isObservable(instance: any): boolean;
|
||||
isWriteableObservable(instance: any): boolean;
|
||||
isComputed(instance: any): boolean;
|
||||
dataFor(node: any): any;
|
||||
removeNode(node: Element): void;
|
||||
cleanNode(node: Element): Element;
|
||||
renderTemplate(template: Function, viewModel: any, options?: any, target?: any, renderMode?: any): any;
|
||||
renderTemplate(template: string, viewModel: any, options?: any, target?: any, renderMode?: any): any;
|
||||
unwrap<T>(value: KnockoutObservable<T> | T): T;
|
||||
|
||||
computedContext: KnockoutComputedContext;
|
||||
|
||||
//////////////////////////////////
|
||||
// templateSources.js
|
||||
//////////////////////////////////
|
||||
|
||||
templateSources: KnockoutTemplateSources;
|
||||
|
||||
//////////////////////////////////
|
||||
// templateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
templateEngine: {
|
||||
|
||||
prototype: KnockoutTemplateEngine;
|
||||
|
||||
new (): KnockoutTemplateEngine;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// templateRewriting.js
|
||||
//////////////////////////////////
|
||||
|
||||
templateRewriting: {
|
||||
|
||||
ensureTemplateIsRewritten(template: Node, templateEngine: KnockoutTemplateEngine, templateDocument: Document): any;
|
||||
ensureTemplateIsRewritten(template: string, templateEngine: KnockoutTemplateEngine, templateDocument: Document): any;
|
||||
|
||||
memoizeBindingAttributeSyntax(htmlString: string, templateEngine: KnockoutTemplateEngine): any;
|
||||
|
||||
applyMemoizedBindingsToNextSibling(bindings: any, nodeName: string): string;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// nativeTemplateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
nativeTemplateEngine: {
|
||||
|
||||
prototype: KnockoutNativeTemplateEngine;
|
||||
|
||||
new (): KnockoutNativeTemplateEngine;
|
||||
|
||||
instance: KnockoutNativeTemplateEngine;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// jqueryTmplTemplateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
jqueryTmplTemplateEngine: {
|
||||
|
||||
prototype: KnockoutTemplateEngine;
|
||||
|
||||
renderTemplateSource(templateSource: Object, bindingContext: KnockoutBindingContext, options: Object): Node[];
|
||||
|
||||
createJavaScriptEvaluatorBlock(script: string): string;
|
||||
|
||||
addTemplate(templateName: string, templateMarkup: string): void;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// templating.js
|
||||
//////////////////////////////////
|
||||
|
||||
setTemplateEngine(templateEngine: KnockoutNativeTemplateEngine): void;
|
||||
|
||||
renderTemplate(template: Function, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: Function, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
|
||||
renderTemplateForEach(template: Function, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
renderTemplateForEach(template: any, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
renderTemplateForEach(template: Function, arrayOrObservableArray: KnockoutObservable<any>, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
renderTemplateForEach(template: any, arrayOrObservableArray: KnockoutObservable<any>, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
|
||||
expressionRewriting: {
|
||||
bindingRewriteValidators: any;
|
||||
parseObjectLiteral: { (objectLiteralString: string): any[] }
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
bindingProvider: {
|
||||
instance: KnockoutBindingProvider;
|
||||
new (): KnockoutBindingProvider;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// selectExtensions.js
|
||||
/////////////////////////////////
|
||||
|
||||
selectExtensions: {
|
||||
|
||||
readValue(element: HTMLElement): any;
|
||||
|
||||
writeValue(element: HTMLElement, value: any): void;
|
||||
};
|
||||
|
||||
components: KnockoutComponents;
|
||||
}
|
||||
|
||||
interface KnockoutBindingProvider {
|
||||
nodeHasBindings(node: Node): boolean;
|
||||
getBindings(node: Node, bindingContext: KnockoutBindingContext): {};
|
||||
getBindingAccessors?(node: Node, bindingContext: KnockoutBindingContext): { [key: string]: string; };
|
||||
}
|
||||
|
||||
interface KnockoutComputedContext {
|
||||
getDependenciesCount(): number;
|
||||
isInitial: () => boolean;
|
||||
isSleeping: boolean;
|
||||
}
|
||||
|
||||
//
|
||||
// refactored types into a namespace to reduce global pollution
|
||||
// and used Union Types to simplify overloads (requires TypeScript 1.4)
|
||||
//
|
||||
declare module KnockoutComponentTypes {
|
||||
|
||||
interface Config {
|
||||
viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
|
||||
template: string | Node[]| DocumentFragment | TemplateElement | AMDModule;
|
||||
synchronous?: boolean;
|
||||
}
|
||||
|
||||
interface ComponentConfig {
|
||||
viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
|
||||
template: any;
|
||||
createViewModel?: any;
|
||||
}
|
||||
|
||||
interface EmptyConfig {
|
||||
}
|
||||
|
||||
// common AMD type
|
||||
interface AMDModule {
|
||||
require: string;
|
||||
}
|
||||
|
||||
// viewmodel types
|
||||
interface ViewModelFunction {
|
||||
(params?: any): any;
|
||||
}
|
||||
|
||||
interface ViewModelSharedInstance {
|
||||
instance: any;
|
||||
}
|
||||
|
||||
interface ViewModelFactoryFunction {
|
||||
createViewModel: (params?: any, componentInfo?: ComponentInfo) => any;
|
||||
}
|
||||
|
||||
interface ComponentInfo {
|
||||
element: Node;
|
||||
templateNodes: Node[];
|
||||
}
|
||||
|
||||
interface TemplateElement {
|
||||
element: string | Node;
|
||||
}
|
||||
|
||||
interface Loader {
|
||||
getConfig? (componentName: string, callback: (result: ComponentConfig) => void): void;
|
||||
loadComponent? (componentName: string, config: ComponentConfig, callback: (result: Definition) => void): void;
|
||||
loadTemplate? (componentName: string, templateConfig: any, callback: (result: Node[]) => void): void;
|
||||
loadViewModel? (componentName: string, viewModelConfig: any, callback: (result: any) => void): void;
|
||||
suppressLoaderExceptions?: boolean;
|
||||
}
|
||||
|
||||
interface Definition {
|
||||
template: Node[];
|
||||
createViewModel? (params: any, options: { element: Node; }): any;
|
||||
}
|
||||
}
|
||||
|
||||
interface KnockoutComponents {
|
||||
// overloads for register method:
|
||||
register(componentName: string, config: KnockoutComponentTypes.Config | KnockoutComponentTypes.EmptyConfig): void;
|
||||
|
||||
isRegistered(componentName: string): boolean;
|
||||
unregister(componentName: string): void;
|
||||
get(componentName: string, callback: (definition: KnockoutComponentTypes.Definition) => void): void;
|
||||
clearCachedDefinition(componentName: string): void
|
||||
defaultLoader: KnockoutComponentTypes.Loader;
|
||||
loaders: KnockoutComponentTypes.Loader[];
|
||||
getComponentNameForNode(node: Node): string;
|
||||
}
|
||||
|
||||
declare var ko: KnockoutStatic;
|
||||
|
||||
declare module "knockout" {
|
||||
export = ko;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
/// <reference path="@ms/odsp.d.ts" />
|
||||
/// <reference path="assertion-error/assertion-error.d.ts" />
|
||||
/// <reference path="knockout/knockout.d.ts" />
|
Loading…
Reference in New Issue