diff --git a/samples/angular-multipage/.editorconfig b/samples/angular-multipage/.editorconfig new file mode 100644 index 000000000..8ffcdc4ec --- /dev/null +++ b/samples/angular-multipage/.editorconfig @@ -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 \ No newline at end of file diff --git a/samples/angular-multipage/.gitattributes b/samples/angular-multipage/.gitattributes new file mode 100644 index 000000000..212566614 --- /dev/null +++ b/samples/angular-multipage/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/samples/angular-multipage/.gitignore b/samples/angular-multipage/.gitignore new file mode 100644 index 000000000..63c4ae010 --- /dev/null +++ b/samples/angular-multipage/.gitignore @@ -0,0 +1,32 @@ +# Logs +logs +*.log +npm-debug.log* + +# Dependency directories +node_modules + +# Build generated files +dist +lib +solution +temp +*.spapp + +# 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 diff --git a/samples/angular-multipage/.npmignore b/samples/angular-multipage/.npmignore new file mode 100644 index 000000000..2c93a9384 --- /dev/null +++ b/samples/angular-multipage/.npmignore @@ -0,0 +1,14 @@ +# Folders +.vscode +coverage +node_modules +sharepoint +src +temp + +# Files +*.csproj +.git* +.yo-rc.json +gulpfile.js +tsconfig.json diff --git a/samples/angular-multipage/.vscode/settings.json b/samples/angular-multipage/.vscode/settings.json new file mode 100644 index 000000000..72890dfce --- /dev/null +++ b/samples/angular-multipage/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + // The number of spaces a tab is equal to. + "editor.tabSize": 2, + + // When enabled, will trim trailing whitespace when you save a file. + "files.trimTrailingWhitespace": true, + + // Controls if the editor should automatically close brackets after opening them + "editor.autoClosingBrackets": false, + + // Configure glob patterns for excluding files and folders. + "search.exclude": { + "**/bower_components": true, + "**/node_modules": true, + "coverage": true, + "dist": true, + "lib-amd": true, + "lib": true, + "temp": true + } +, +"typescript.tsdk": "./node_modules/typescript/lib" +} diff --git a/samples/angular-multipage/.vscode/tasks.json b/samples/angular-multipage/.vscode/tasks.json new file mode 100644 index 000000000..5204908d6 --- /dev/null +++ b/samples/angular-multipage/.vscode/tasks.json @@ -0,0 +1,34 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "0.1.0", + "command": "gulp", + "isShellCommand": true, + "showOutput": "always", + "args": [ + "--no-color" + ], + "tasks": [ + { + "taskName": "bundle", + "isBuildCommand": true, + "problemMatcher": [ + "$tsc" + ] + }, + { + "taskName": "test", + "isTestCommand": true, + "problemMatcher": [ + "$tsc" + ] + }, + { + "taskName": "serve", + "isWatching": true, + "problemMatcher": [ + "$tsc" + ] + } + ] +} diff --git a/samples/angular-multipage/.yo-rc.json b/samples/angular-multipage/.yo-rc.json new file mode 100644 index 000000000..758614738 --- /dev/null +++ b/samples/angular-multipage/.yo-rc.json @@ -0,0 +1,7 @@ +{ + "@microsoft/generator-sharepoint": { + "libraryName": "angular-multipage", + "libraryId": "2edf4e93-fd5d-4c59-8b46-480af77c2233", + "framework": "none" + } +} \ No newline at end of file diff --git a/samples/angular-multipage/README.md b/samples/angular-multipage/README.md new file mode 100644 index 000000000..bab647447 --- /dev/null +++ b/samples/angular-multipage/README.md @@ -0,0 +1,83 @@ +# Angular multi-page client-side web part + +## Summary + +Sample SharePoint Framework client-side web parts built using Angular illustrating building multi-page web parts. + +### Poll + +Sample poll web part allowing users to vote and view the results. + +![Poll web part built on the SharePoint Framework using Angular](./assets/poll-preview.gif) + +## 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-multipage|Waldek Mastykarz (MVP, Rencore, @waldekm) + +## Version history + +Version|Date|Comments +-------|----|-------- +1.0.0|November 1, 2016|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.** + +--- + +## Prerequisites + +- Site Collection created under the **/sites/** Managed Path + +## Minimal Path to Awesome + +### Poll web part + +- create list for the poll + - in SharePoint create a new list + - in the list add new column called `NumVotes` of type **Number** (you can change the name later if you want) + - in the list add a few items - each representing one of the vote options in your poll (for example for a poll about favorite JavaScript frameworks you would add items like _Angular_, _React_, _jQuery_, etc.) +- deploy SharePoint workbench + - clone this repo + - in the command line run + - `npm i` + - `gulp serve --nobrowser` + - from the **./temp** directory create a copy of the **workbench.html** file and rename it to **workbench.aspx** + - in the **workbench.aspx** file change the value of the **webAbsoluteUrl** property to the absolute URL of your SharePoint site + - upload the **workbench.aspx** file to a document library in your site +- use the web part + - in your web browser navigate to the **workbench.aspx** page uploaded in your SharePoint site + - add the Poll web part to the canvas + - in the configuration specify the **Poll title** and optionally the **Poll description**. Also specify the title of your poll list + - confirm the changes by clicking the **Apply** button + - select one of the vote options and click the **Vote** button to submit your vote + +![Poll web part built on the SharePoint Framework using Angular](./assets/poll-preview.gif) + +## Features + +This project contains sample client-side web parts built on the SharePoint Framework using Angular illustrating working with multi-page web parts. + +This sample illustrates the following concepts on top of the SharePoint Framework: + +- using Angular v1.x with TypeScript for building SharePoint Framework client-side web parts +- using Angular UI Router for building multi-page web parts +- navigating between the different pages without changing the URL +- building parent and child states with Angular UI Router +- passing web part configuration into an Angular application +- reacting to Angular events in a SharePoint Framework client-side web part +- styling Angular applications using Office UI Fabric +- using non-reactive web part property pane +- using conditional rendering for one-time web part setup +- chaining multiple Angular promises +- reading and updating SharePoint list items using Angular +- showing charts using [Chart.js](http://www.chartjs.org) and [Angular Chart directives](https://jtblin.github.io/angular-chart.js/) + + \ No newline at end of file diff --git a/samples/angular-multipage/angular-multipage.njsproj b/samples/angular-multipage/angular-multipage.njsproj new file mode 100644 index 000000000..8ef9c7a7a --- /dev/null +++ b/samples/angular-multipage/angular-multipage.njsproj @@ -0,0 +1,86 @@ + + + + Debug + 2.0 + {2edf4e93-fd5d-4c59-8b46-480af77c2233} + + ProjectFiles + node_modules\gulp\bin\gulp.js + . + . + {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} + true + CommonJS + false + 11.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + serve + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + True + 0 + / + http://localhost:48022/ + False + True + http://localhost:1337 + False + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + False + False + + + + + \ No newline at end of file diff --git a/samples/angular-multipage/assets/poll-preview.gif b/samples/angular-multipage/assets/poll-preview.gif new file mode 100644 index 000000000..202d9d628 Binary files /dev/null and b/samples/angular-multipage/assets/poll-preview.gif differ diff --git a/samples/angular-multipage/config/config.json b/samples/angular-multipage/config/config.json new file mode 100644 index 000000000..655ca2b49 --- /dev/null +++ b/samples/angular-multipage/config/config.json @@ -0,0 +1,22 @@ +{ + "entries": [ + { + "entry": "./lib/webparts/poll/PollWebPart.js", + "manifest": "./src/webparts/poll/PollWebPart.manifest.json", + "outputPath": "./dist/poll.bundle.js" + } + ], + "externals": { + "@microsoft/sp-client-base": "node_modules/@microsoft/sp-client-base/dist/sp-client-base.js", + "@microsoft/sp-client-preview": "node_modules/@microsoft/sp-client-preview/dist/sp-client-preview.js", + "@microsoft/sp-lodash-subset": "node_modules/@microsoft/sp-lodash-subset/dist/sp-lodash-subset.js", + "office-ui-fabric-react": "node_modules/office-ui-fabric-react/dist/office-ui-fabric-react.js", + "react": "node_modules/react/dist/react.min.js", + "react-dom": "node_modules/react-dom/dist/react-dom.min.js", + "react-dom/server": "node_modules/react-dom/dist/react-dom-server.min.js", + "moment": "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.2/moment.min.js" + }, + "localizedResources": { + "pollStrings": "webparts/poll/loc/{locale}.js" + } +} diff --git a/samples/angular-multipage/config/deploy-azure-storage.json b/samples/angular-multipage/config/deploy-azure-storage.json new file mode 100644 index 000000000..add0a50c4 --- /dev/null +++ b/samples/angular-multipage/config/deploy-azure-storage.json @@ -0,0 +1,6 @@ +{ + "workingDir": "./temp/deploy/", + "account": "", + "container": "angular-multipage", + "accessKey": "" +} \ No newline at end of file diff --git a/samples/angular-multipage/config/package-solution.json b/samples/angular-multipage/config/package-solution.json new file mode 100644 index 000000000..41b4a06df --- /dev/null +++ b/samples/angular-multipage/config/package-solution.json @@ -0,0 +1,10 @@ +{ + "solution": { + "name": "angular-multipage-client-side-solution", + "id": "2edf4e93-fd5d-4c59-8b46-480af77c2233", + "version": "1.0.0.0" + }, + "paths": { + "zippedPackage": "solution/angular-multipage.spapp" + } +} diff --git a/samples/angular-multipage/config/prepare-deploy.json b/samples/angular-multipage/config/prepare-deploy.json new file mode 100644 index 000000000..6aca63656 --- /dev/null +++ b/samples/angular-multipage/config/prepare-deploy.json @@ -0,0 +1,3 @@ +{ + "deployCdnPath": "temp/deploy" +} diff --git a/samples/angular-multipage/config/serve.json b/samples/angular-multipage/config/serve.json new file mode 100644 index 000000000..087899637 --- /dev/null +++ b/samples/angular-multipage/config/serve.json @@ -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/" + } +} diff --git a/samples/angular-multipage/config/tslint.json b/samples/angular-multipage/config/tslint.json new file mode 100644 index 000000000..bf3362c87 --- /dev/null +++ b/samples/angular-multipage/config/tslint.json @@ -0,0 +1,51 @@ +{ + // 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, + "a11y-role": true + } + } +} \ No newline at end of file diff --git a/samples/angular-multipage/config/write-manifests.json b/samples/angular-multipage/config/write-manifests.json new file mode 100644 index 000000000..0a4bafb06 --- /dev/null +++ b/samples/angular-multipage/config/write-manifests.json @@ -0,0 +1,3 @@ +{ + "cdnBasePath": "" +} \ No newline at end of file diff --git a/samples/angular-multipage/gulpfile.js b/samples/angular-multipage/gulpfile.js new file mode 100644 index 000000000..7d36ddb1c --- /dev/null +++ b/samples/angular-multipage/gulpfile.js @@ -0,0 +1,6 @@ +'use strict'; + +const gulp = require('gulp'); +const build = require('@microsoft/sp-build-web'); + +build.initialize(gulp); diff --git a/samples/angular-multipage/package.json b/samples/angular-multipage/package.json new file mode 100644 index 000000000..bad4f9435 --- /dev/null +++ b/samples/angular-multipage/package.json @@ -0,0 +1,34 @@ +{ + "name": "angular-multipage", + "version": "1.0.0", + "private": true, + "engines": { + "node": ">=0.10.0" + }, + "author": { + "name": "Waldek Mastykarz", + "url": "https://blog.mastykarz.nl" + }, + "dependencies": { + "@microsoft/sp-client-base": "~0.4.0", + "@microsoft/sp-client-preview": "~0.5.0", + "@types/angular": "^1.5.17", + "@types/angular-ui-router": "^1.1.34", + "@types/chart.js": "0.0.7", + "angular": "^1.5.8", + "angular-chart.js": "^1.0.3", + "angular-ui-router": "^0.3.1", + "chart.js": "^2.3.0" + }, + "devDependencies": { + "@microsoft/sp-build-web": "~0.7.0", + "@microsoft/sp-module-interfaces": "~0.4.0", + "@microsoft/sp-webpart-workbench": "~0.5.0", + "gulp": "~3.9.1" + }, + "scripts": { + "build": "gulp bundle", + "clean": "gulp nuke", + "test": "gulp test" + } +} diff --git a/samples/angular-multipage/src/tests.js b/samples/angular-multipage/src/tests.js new file mode 100644 index 000000000..cb4bb5cf2 --- /dev/null +++ b/samples/angular-multipage/src/tests.js @@ -0,0 +1,5 @@ +var context = require.context('.', true, /.+\.test\.js?$/); + +context.keys().forEach(context); + +module.exports = context; diff --git a/samples/angular-multipage/src/webparts/poll/IConfigurationChanged.ts b/samples/angular-multipage/src/webparts/poll/IConfigurationChanged.ts new file mode 100644 index 000000000..4559d18ba --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/IConfigurationChanged.ts @@ -0,0 +1,9 @@ +import { DisplayMode } from '@microsoft/sp-client-base'; + +export interface IConfigurationChanged { + listName: string; + sharePointApiUrl: string; + title: string; + description: string; + displayMode: DisplayMode; +} \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/IPollWebPartProps.ts b/samples/angular-multipage/src/webparts/poll/IPollWebPartProps.ts new file mode 100644 index 000000000..4cc33db30 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/IPollWebPartProps.ts @@ -0,0 +1,5 @@ +export interface IPollWebPartProps { + listName: string; + pollTitle: string; + pollDescription: string; +} diff --git a/samples/angular-multipage/src/webparts/poll/Poll.module.scss b/samples/angular-multipage/src/webparts/poll/Poll.module.scss new file mode 100644 index 000000000..8eb2e9f6b --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/Poll.module.scss @@ -0,0 +1,7 @@ +.poll { + .container { + max-width: 700px; + margin: 0px auto; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); + } +} diff --git a/samples/angular-multipage/src/webparts/poll/PollWebPart.manifest.json b/samples/angular-multipage/src/webparts/poll/PollWebPart.manifest.json new file mode 100644 index 000000000..f1f3a41e0 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/PollWebPart.manifest.json @@ -0,0 +1,21 @@ +{ + "$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json", + + "id": "2527c144-5b77-4709-8d14-4313b7380dd1", + "componentType": "WebPart", + "version": "0.0.1", + "manifestVersion": 2, + + "preconfiguredEntries": [{ + "groupId": "2527c144-5b77-4709-8d14-4313b7380dd1", + "group": { "default": "Content" }, + "title": { "default": "Poll" }, + "description": { "default": "Vote and see the results" }, + "officeFabricIconFontName": "CheckboxComposite", + "properties": { + "listName": "", + "pollTitle": "", + "pollDescription": "" + } + }] +} diff --git a/samples/angular-multipage/src/webparts/poll/PollWebPart.ts b/samples/angular-multipage/src/webparts/poll/PollWebPart.ts new file mode 100644 index 000000000..4ad52b40f --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/PollWebPart.ts @@ -0,0 +1,101 @@ +import { + BaseClientSideWebPart, + IPropertyPaneSettings, + IWebPartContext, + PropertyPaneTextField +} from '@microsoft/sp-client-preview'; +import * as angular from 'angular'; + +import styles from './Poll.module.scss'; +import * as strings from 'pollStrings'; +import { IPollWebPartProps } from './IPollWebPartProps'; +import { IConfigurationChanged } from './IConfigurationChanged'; +import './app/app.module'; + +export default class PollWebPart extends BaseClientSideWebPart { + private $injector: ng.auto.IInjectorService; + + public constructor(context: IWebPartContext) { + super(context); + } + + public render(): void { + if (this.renderedOnce === false) { + this.domElement.innerHTML = ` + + + `; + + this.$injector = angular.bootstrap(this.domElement, ['poll']); + } + + const $rootScope: angular.IRootScopeService = this.$injector.get('$rootScope'); + $rootScope.$broadcast('configurationChanged', { + listName: this.properties.listName, + sharePointApiUrl: this.context.pageContext.web.absoluteUrl + '/_api', + title: this.properties.pollTitle, + description: this.properties.pollDescription, + displayMode: this.displayMode + }); + $rootScope.$on('startConfiguration', (event: angular.IAngularEvent): void => { + this.configureStart(); + }); + } + + protected get propertyPaneSettings(): IPropertyPaneSettings { + return { + pages: [ + { + header: { + description: strings.PropertyPaneDescription + }, + groups: [ + { + groupName: strings.ViewGroupName, + groupFields: [ + PropertyPaneTextField('pollTitle', { + label: strings.PollTitleFieldLabel, + onGetErrorMessage: this.validatePollTitle + }), + PropertyPaneTextField('pollDescription', { + label: strings.PollDescriptionFieldLabel + }) + ] + }, + { + groupName: strings.DataGroupName, + groupFields: [ + PropertyPaneTextField('listName', { + label: strings.ListNameFieldLabel, + onGetErrorMessage: this.validateListName + }) + ] + } + ] + } + ] + }; + } + + private validatePollTitle(pollTitle: string): string { + if (pollTitle.trim().length === 0) { + return 'Please enter title of this poll'; + } + else { + return ''; + } + } + + private validateListName(listName: string): string { + if (listName.trim().length === 0) { + return 'Please enter the name of the list'; + } + else { + return ''; + } + } + + protected get disableReactivePropertyChanges(): boolean { + return true; + } +} diff --git a/samples/angular-multipage/src/webparts/poll/app/AppController.ts b/samples/angular-multipage/src/webparts/poll/app/AppController.ts new file mode 100644 index 000000000..0ab49b5d6 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/AppController.ts @@ -0,0 +1,32 @@ +import * as angular from 'angular'; +import { DisplayMode } from '@microsoft/sp-client-base'; +import { IConfigurationChanged } from '../IConfigurationChanged'; + +export interface IAppControllerState { +} + +export class AppController implements IAppControllerState { + public static $inject: string[] = ['$rootScope', '$state']; + + constructor($rootScope: angular.IRootScopeService, private $state: angular.ui.IStateService) { + $rootScope.$on('configurationChanged', (event: angular.IAngularEvent, args: IConfigurationChanged): void => { + this.init(args.listName, args.sharePointApiUrl, args.title, args.description, args.displayMode); + }); + } + + private init(listName: string, sharePointApiUrl: string, title: string, description: string, displayMode: DisplayMode): void { + if (!listName || listName.trim().length === 0) { + this.$state.go('config', { + displayMode: displayMode + }); + } + else { + this.$state.go('poll.vote', { + title: title, + description: description, + listName: listName, + sharePointApiUrl: sharePointApiUrl + }); + } + } +} diff --git a/samples/angular-multipage/src/webparts/poll/app/app.module.ts b/samples/angular-multipage/src/webparts/poll/app/app.module.ts new file mode 100644 index 000000000..4bea0a0c5 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/app.module.ts @@ -0,0 +1,25 @@ +import * as angular from 'angular'; +import 'angular-ui-router'; +import 'angular-chart.js'; +import { AppController } from './AppController'; +import { ConfigController } from './config/ConfigController'; +import { PollController } from './poll/PollController'; +import { VoteController } from './poll/vote/VoteController'; +import { ResultsController } from './poll/results/ResultsController'; +import { PollService } from './services/PollService'; +import { SpinnerDirective } from './directives/SpinnerDirective'; + +angular + .module('poll', [ + 'ui.router', + 'chart.js' + ]) + .controller('appController', AppController) + .controller('configController', ConfigController) + .controller('pollController', PollController) + .controller('voteController', VoteController) + .controller('resultsController', ResultsController) + .service('PollService', PollService) + .directive('spinner', SpinnerDirective.factory()); + +require('./app.states'); diff --git a/samples/angular-multipage/src/webparts/poll/app/app.states.ts b/samples/angular-multipage/src/webparts/poll/app/app.states.ts new file mode 100644 index 000000000..9ce457451 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/app.states.ts @@ -0,0 +1,46 @@ +import * as angular from 'angular'; + +angular + .module('poll') + .config(uiRouterConfigurator); + +uiRouterConfigurator.$inject = ['$stateProvider', '$urlRouterProvider']; + +function uiRouterConfigurator($stateProvider: ng.ui.IStateProvider, $urlRouterProvider: ng.ui.IUrlRouterProvider): void { + $stateProvider + .state('config', { + template: require('./config/config.html'), + params: { + displayMode: undefined + }, + controller: 'configController', + controllerAs: 'vm' + }) + .state('poll', { + template: require('./poll/poll.html'), + params: { + title: undefined, + description: undefined + }, + controller: 'pollController', + controllerAs: 'vm' + }) + .state('poll.vote', { + template: require('./poll/vote/vote.html'), + params: { + listName: undefined, + sharePointApiUrl: undefined + }, + controller: 'voteController', + controllerAs: 'vm' + }) + .state('poll.results', { + template: require('./poll/results/results.html'), + params: { + listName: undefined, + sharePointApiUrl: undefined + }, + controller: 'resultsController', + controllerAs: 'vm' + }); +} \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/config/ConfigController.ts b/samples/angular-multipage/src/webparts/poll/app/config/ConfigController.ts new file mode 100644 index 000000000..074e62eb9 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/config/ConfigController.ts @@ -0,0 +1,27 @@ +import * as angular from 'angular'; +import { DisplayMode } from '@microsoft/sp-client-base'; + +export interface IConfigControllerState { + isEditMode: boolean; + configure: ($event: MouseEvent) => void; +} + +export class ConfigController implements IConfigControllerState { + public static $inject: string[] = ['$stateParams', '$rootScope']; + + public isEditMode: boolean; + + constructor($stateParams: angular.ui.IStateParamsService, private $rootScope: angular.IRootScopeService) { + this.init($stateParams['displayMode']); + } + + private init(displayMode: DisplayMode): void { + this.isEditMode = displayMode === DisplayMode.Edit; + } + + public configure($event: MouseEvent): void { + $event.preventDefault(); + + this.$rootScope.$broadcast('startConfiguration'); + } +} diff --git a/samples/angular-multipage/src/webparts/poll/app/config/config.html b/samples/angular-multipage/src/webparts/poll/app/config/config.html new file mode 100644 index 000000000..b5c572587 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/config/config.html @@ -0,0 +1,23 @@ + + + + + + + + Poll + + + + + + Find out what others think. + + + + Configure + + + + \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/directives/SpinnerDirective.ts b/samples/angular-multipage/src/webparts/poll/app/directives/SpinnerDirective.ts new file mode 100644 index 000000000..bc971fe8d --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/directives/SpinnerDirective.ts @@ -0,0 +1,189 @@ +import * as angular from 'angular'; + +export enum SpinnerSize { + 'small', + 'large' +} + +export class SpinnerDirective implements angular.IDirective { + public restrict: string = 'E'; + public transclude: boolean = true; + public replace: boolean = true; + public template: string = ''; + public controller: any = SpinnerController; + public scope: any = { + 'ngShow': '=', + 'uifSize': '@' + }; + + public static factory(): angular.IDirectiveFactory { + const directive: angular.IDirectiveFactory = () => new SpinnerDirective(); + return directive; + } + + public link( + scope: ISpinnerScope, + instanceElement: angular.IAugmentedJQuery, + attrs: ISpinnerAttributes, + controller: SpinnerController, + $transclude: angular.ITranscludeFunction): void { + + if (angular.isDefined(attrs.uifSize)) { + if (angular.isUndefined(SpinnerSize[attrs.uifSize])) { + + controller.$log.error('Error [ngOfficeUiFabric] officeuifabric.components.spinner - Unsupported size: ' + + 'Spinner size (\'' + attrs.uifSize + '\') is not supported by the Office UI Fabric.'); + } + + if (SpinnerSize[attrs.uifSize] === SpinnerSize.large) { + instanceElement.addClass('ms-Spinner--large'); + } + } + + if (attrs.ngShow != null) { + scope.$watch('ngShow', (newVisible: boolean, oldVisible: boolean, spinnerScope: ISpinnerScope): void => { + if (newVisible) { + spinnerScope.start(); + } else { + spinnerScope.stop(); + } + }); + } else { + scope.start(); + } + + $transclude((clone: angular.IAugmentedJQuery) => { + if (clone.length > 0) { + const wrapper: angular.IAugmentedJQuery = angular.element(''); + wrapper.addClass('ms-Spinner-label').append(clone); + instanceElement.append(wrapper); + } + }); + + scope.init(); + } +} + +export interface ISpinnerScope extends angular.IScope { + start: () => void; + stop: () => void; + init: () => void; + ngShow: boolean; + uifSize: string; +} + +export class SpinnerController { + + public static $inject: string[] = ['$scope', '$element', '$interval', '$log']; + + private _offsetSize: number = 0.179; + private _numCircles: number = 8; + private _animationSpeed: number = 90; + private _circles: CircleObject[] = []; + private _fadeIncrement: number; + private _animationInterval: angular.IPromise; + private _parentSize: number; + + constructor( + public $scope: ISpinnerScope, + private $element: angular.IAugmentedJQuery, + private $interval: angular.IIntervalService, + public $log: angular.ILogService) { + + $scope.init = (): void => { + this._parentSize = SpinnerSize[this.$scope.uifSize] === SpinnerSize.large ? 28 : 20; + this.createCirclesAndArrange(); + this.setInitialOpacity(); + }; + + $scope.start = (): void => { + this._animationInterval = $interval( + () => { + let i: number = this._circles.length; + while (i--) { + this.fadeCircle(this._circles[i]); + } + }, + this._animationSpeed); + }; + + $scope.stop = (): void => { + $interval.cancel(this._animationInterval); + }; + } + + private createCirclesAndArrange(): void { + + let angle: number = 0; + const offset: number = this._parentSize * this._offsetSize; + const step: number = (2 * Math.PI) / this._numCircles; + let i: number = this._numCircles; + const radius: number = (this._parentSize - offset) * 0.5; + + while (i--) { + const circle: angular.IAugmentedJQuery = this.createCircle(); + + const x: number = Math.round(this._parentSize * 0.5 + radius * Math.cos(angle) - circle[0].clientWidth * 0.5) - offset * 0.5; + const y: number = Math.round(this._parentSize * 0.5 + radius * Math.sin(angle) - circle[0].clientHeight * 0.5) - offset * 0.5; + + this.$element.append(circle); + + circle.css('left', (x + 'px')); + circle.css('top', (y + 'px')); + + angle += step; + + const circleObject: CircleObject = new CircleObject(circle, i); + this._circles.push(circleObject); + } + } + + private createCircle(): angular.IAugmentedJQuery { + const circle: angular.IAugmentedJQuery = angular.element(''); + const dotSize: string = (this._parentSize * this._offsetSize) + 'px'; + circle.addClass('ms-Spinner-circle').css('width', dotSize).css('height', dotSize); + + return circle; + }; + + private setInitialOpacity(): void { + let opcaityToSet: number; + this._fadeIncrement = 1 / this._numCircles; + + this._circles.forEach((circle: CircleObject, index: number) => { + opcaityToSet = (this._fadeIncrement * (index + 1)); + circle.opacity = opcaityToSet; + }); + } + + private fadeCircle(circle: CircleObject): void { + let newOpacity: number = circle.opacity - this._fadeIncrement; + + if (newOpacity <= 0) { + newOpacity = 1; + } + + circle.opacity = newOpacity; + } + +} + +class CircleObject { + constructor( + public circleElement: angular.IAugmentedJQuery, + public circleIndex: number) { + } + + public get opacity(): number { + return +(this.circleElement.css('opacity')); + } + + public set opacity(opacity: number) { + this.circleElement.css('opacity', opacity); + } +} + +export interface ISpinnerAttributes extends angular.IAttributes { + uifSize?: string; + ngShow?: any; +} \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/poll/PollController.ts b/samples/angular-multipage/src/webparts/poll/app/poll/PollController.ts new file mode 100644 index 000000000..e3da0a24e --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/poll/PollController.ts @@ -0,0 +1,22 @@ +import * as angular from 'angular'; + +export interface IPollControllerState { + title: string; + description: string; +} + +export class PollController implements IPollControllerState { + public static $inject: string[] = ['$stateParams']; + + public title: string; + public description: string; + + constructor(private $stateParams: angular.ui.IStateParamsService) { + this.init($stateParams['title'], $stateParams['description']); + } + + private init(title: string, description: string): void { + this.title = title; + this.description = description; + } +} diff --git a/samples/angular-multipage/src/webparts/poll/app/poll/poll.html b/samples/angular-multipage/src/webparts/poll/app/poll/poll.html new file mode 100644 index 000000000..367cfc727 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/poll/poll.html @@ -0,0 +1,4 @@ +{{::vm.title}} +{{::vm.description}} + + \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/poll/results/ResultsController.ts b/samples/angular-multipage/src/webparts/poll/app/poll/results/ResultsController.ts new file mode 100644 index 000000000..22e0c0549 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/poll/results/ResultsController.ts @@ -0,0 +1,74 @@ +import * as angular from 'angular'; +import { IPollService, IVoteResult } from '../../services/PollService'; + +export interface IResultsControllerScope { + loading: boolean; + error: string; + data: number[][]; + labels: string[]; + series: string[]; + options: any; +} + +export class ResultsController implements IResultsControllerScope { + public static $inject: string[] = ['PollService', '$stateParams']; + + public loading: boolean; + public error: string; + public data: number[][]; + public labels: string[]; + public series: string[]; + public options: any; + + private listName: string; + private sharePointApiUrl: string; + + constructor(private pollService: IPollService, $stateParams: angular.ui.IStateParamsService) { + this.init($stateParams['listName'], $stateParams['sharePointApiUrl']); + } + + private init(listName: string, sharePointApiUrl: string): void { + this.error = undefined; + + this.listName = listName; + this.sharePointApiUrl = sharePointApiUrl; + this.loadResults(); + } + + public loadResults(): void { + this.loading = true; + this.error = undefined; + + this.pollService.getResults(this.listName, this.sharePointApiUrl) + .then((results: IVoteResult[]): void => { + this.labels = []; + this.series = ['Number of votes']; + this.data = []; + this.data[0] = []; + this.options = { + scales: { + xAxes: [{ + gridLines: { + display: false + }, + scaleLabel: { + display: true, + labelString: 'Number of votes' + } + }] + } + }; + + for (let i: number = 0; i < results.length; i++) { + const result: IVoteResult = results[i]; + this.labels.push(result.label); + this.data[0].push(result.numVotes); + } + }, (error: any): void => { + this.error = error; + }) + .finally((): void => { + this.loading = false; + }); + } +} diff --git a/samples/angular-multipage/src/webparts/poll/app/poll/results/results.html b/samples/angular-multipage/src/webparts/poll/app/poll/results/results.html new file mode 100644 index 000000000..f4ef70dd0 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/poll/results/results.html @@ -0,0 +1,11 @@ + + + Loading... + + + + + + + An error has occured while loading vote options: {{::vm.error.data['odata.error'].message.value}} + \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/poll/vote/VoteController.ts b/samples/angular-multipage/src/webparts/poll/app/poll/vote/VoteController.ts new file mode 100644 index 000000000..ede460792 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/poll/vote/VoteController.ts @@ -0,0 +1,83 @@ +import * as angular from 'angular'; +import { IPollService, IVoteOption } from '../../services/PollService'; +import { IConfigurationChanged } from '../../../IConfigurationChanged'; + +export interface IVoteControllerScope { + loading: boolean; + error: string; + voteOptions: IVoteOption[]; + vote: ($event: MouseEvent) => void; + voteOptionId: number; + voting: boolean; + selectVoteOption: (voteOptionId: number, $event: MouseEvent) => void; +} + +export class VoteController implements IVoteControllerScope { + public static $inject: string[] = ['PollService', '$state', '$stateParams']; + + public loading: boolean; + public error: string; + public voteOptions: IVoteOption[]; + public voteOptionId: number; + public voting: boolean; + + private listName: string; + private sharePointApiUrl: string; + + constructor(private pollService: IPollService, private $state: angular.ui.IStateService, $stateParams: angular.ui.IStateParamsService) { + this.init($stateParams['listName'], $stateParams['sharePointApiUrl']); + } + + private init(listName: string, sharePointApiUrl: string): void { + this.error = undefined; + + this.listName = listName; + this.sharePointApiUrl = sharePointApiUrl; + this.loadVoteOptions(); + } + + private loadVoteOptions(): void { + this.loading = true; + this.error = undefined; + + this.pollService.getVoteOptions(this.listName, this.sharePointApiUrl) + .then((voteOptions: IVoteOption[]): void => { + this.voteOptions = voteOptions; + }, (error: any): void => { + this.error = error; + }) + .finally((): void => { + this.loading = false; + }); + } + + public vote($event: MouseEvent): void { + event.preventDefault(); + + this.voting = true; + this.error = undefined; + + this.pollService.vote(this.voteOptionId, this.listName, this.sharePointApiUrl) + .then((): void => { + this.$state.go('poll.results', { + listName: this.listName, + sharePointApiUrl: this.sharePointApiUrl + }); + }, (error: any): void => { + this.error = error; + }) + .finally((): void => { + this.voting = false; + }); + } + + public selectVoteOption(voteOptionId: number, $event: MouseEvent): void { + $event.preventDefault(); + + if (this.voting) { + return; + } + + this.voteOptionId = voteOptionId; + } +} \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/poll/vote/vote.html b/samples/angular-multipage/src/webparts/poll/app/poll/vote/vote.html new file mode 100644 index 000000000..8002e04dd --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/poll/vote/vote.html @@ -0,0 +1,26 @@ + + + Loading... + + + + + + + {{::option.label}} + + + + + + Vote + + + + Voting... + + + + An error has occured while loading vote options: {{::vm.error.data['odata.error'].message.value}} + \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/app/services/PollService.ts b/samples/angular-multipage/src/webparts/poll/app/services/PollService.ts new file mode 100644 index 000000000..a177cd492 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/app/services/PollService.ts @@ -0,0 +1,175 @@ +import * as angular from 'angular'; + +export interface IVoteOption { + id: number; + label: string; +} + +export interface IVoteResult extends IVoteOption { + numVotes: number; +} + +interface IVoteOptionItem { + Id: number; + Title: string; + NumVotes?: number; +} + +export interface IPollService { + getVoteOptions: (listName: string, sharePointApiUrl: string) => angular.IPromise; + vote: (voteOptionId: number, listName: string, sharePointApiUrl: string) => angular.IPromise; + getResults: (listName: string, sharePointApiUrl: string) => angular.IPromise; +} + +export class PollService implements IPollService { + public static $inject: string[] = ['$http', '$q']; + + constructor(private $http: angular.IHttpService, private $q: angular.IQService) { + } + + public getVoteOptions(listName: string, sharePointApiUrl: string): angular.IPromise { + const deferred: angular.IDeferred = this.$q.defer(); + + this.$http({ + method: 'GET', + url: sharePointApiUrl + `/web/lists/getByTitle('${listName}')/items?$select=Id,Title`, + headers: { + 'Accept': 'application/json;odata=nometadata' + } + }) + .then((result: angular.IHttpPromiseCallbackArg<{ value: IVoteOptionItem[] }>): void => { + const voteOptions: IVoteOption[] = []; + for (let i: number = 0; i < result.data.value.length; i++) { + const item: IVoteOptionItem = result.data.value[i]; + voteOptions.push({ + id: item.Id, + label: item.Title + }); + } + deferred.resolve(voteOptions); + }, (error: any): void => { + deferred.reject(error); + }); + + return deferred.promise; + } + + public vote(voteOptionId: number, listName: string, sharePointApiUrl: string): angular.IPromise { + const deferred: angular.IDeferred = this.$q.defer(); + + let requestDigest: string = undefined; + let listItemEntityTypeName: string = undefined; + + this.getRequestDigest(sharePointApiUrl) + .then((digest: string): angular.IPromise => { + requestDigest = digest; + + return this.getListItemEntityTypeName(listName, sharePointApiUrl); + }) + .then((itemEntityTypeName: string): angular.IPromise => { + listItemEntityTypeName = itemEntityTypeName; + + return this.$http({ + method: 'GET', + url: sharePointApiUrl + `/web/lists/getByTitle('${listName}')/items('${voteOptionId}')?$select=NumVotes`, + headers: { + 'Accept': 'application/json;odata=nometadata' + } + }); + }) + .then((result: angular.IHttpPromiseCallbackArg): angular.IPromise<{}> => { + const body: string = JSON.stringify({ + '__metadata': { + 'type': listItemEntityTypeName + }, + 'NumVotes': result.data.NumVotes && !isNaN(result.data.NumVotes) ? result.data.NumVotes+1 : 1 + }); + + return this.$http({ + url: `${sharePointApiUrl}/web/lists/getByTitle('${listName}')/items(${voteOptionId})`, + method: 'POST', + headers: { + 'Accept': 'application/json;odata=nometadata', + 'Content-type': 'application/json;odata=verbose', + 'X-RequestDigest': requestDigest, + 'IF-MATCH': result.headers('ETag'), + 'X-HTTP-Method': 'MERGE' + }, + data: body + }); + }) + .then((): void => { + deferred.resolve(); + }, (error: any): void => { + deferred.reject(error); + }); + + return deferred.promise; + } + + public getResults(listName: string, sharePointApiUrl: string): angular.IPromise { + const deferred: angular.IDeferred = this.$q.defer(); + + this.$http({ + method: 'GET', + url: sharePointApiUrl + `/web/lists/getByTitle('${listName}')/items?$select=Id,Title,NumVotes`, + headers: { + 'Accept': 'application/json;odata=nometadata' + } + }) + .then((result: angular.IHttpPromiseCallbackArg<{ value: IVoteOptionItem[] }>): void => { + const voteResults: IVoteResult[] = []; + for (let i: number = 0; i < result.data.value.length; i++) { + const item: IVoteOptionItem = result.data.value[i]; + voteResults.push({ + id: item.Id, + label: item.Title, + numVotes: item.NumVotes || 0 + }); + } + deferred.resolve(voteResults); + }, (error: any): void => { + deferred.reject(error); + }); + + return deferred.promise; + } + + private getRequestDigest(sharePointApiUrl: string): angular.IPromise { + const deferred: angular.IDeferred = this.$q.defer(); + + this.$http({ + method: 'POST', + url: sharePointApiUrl + '/contextinfo', + headers: { + 'Accept': 'application/json;odata=nometadata' + } + }) + .then((result: angular.IHttpPromiseCallbackArg<{ FormDigestValue: string }>): void => { + deferred.resolve(result.data.FormDigestValue); + }, (error: any): void => { + deferred.reject(error); + }); + + return deferred.promise; + } + + private getListItemEntityTypeName(listName: string, sharePointApiUrl: string): angular.IPromise { + const deferred: angular.IDeferred = this.$q.defer(); + + this.$http({ + url: `${sharePointApiUrl}/web/lists/getByTitle('${listName}')?$select=ListItemEntityTypeFullName`, + method: 'GET', + headers: { + 'Accept': 'application/json;odata=nometadata' + } + }) + .then((result: angular.IHttpPromiseCallbackArg<{ ListItemEntityTypeFullName: string }>): void => { + deferred.resolve(result.data.ListItemEntityTypeFullName); + }, (error: any): void => { + deferred.reject(error); + }); + + return deferred.promise; + } +} \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/loc/en-us.js b/samples/angular-multipage/src/webparts/poll/loc/en-us.js new file mode 100644 index 000000000..13d5ad583 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/loc/en-us.js @@ -0,0 +1,10 @@ +define([], function() { + return { + "PropertyPaneDescription": "Configure properties of this poll", + "DataGroupName": "Data", + "ViewGroupName": "View", + "ListNameFieldLabel": "List name", + "PollTitleFieldLabel": "Poll title", + "PollDescriptionFieldLabel": "Poll description (optional)" + } +}); \ No newline at end of file diff --git a/samples/angular-multipage/src/webparts/poll/loc/mystrings.d.ts b/samples/angular-multipage/src/webparts/poll/loc/mystrings.d.ts new file mode 100644 index 000000000..222310e69 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/loc/mystrings.d.ts @@ -0,0 +1,13 @@ +declare interface IPollStrings { + PropertyPaneDescription: string; + DataGroupName: string; + ViewGroupName: string; + ListNameFieldLabel: string; + PollTitleFieldLabel: string; + PollDescriptionFieldLabel: string; +} + +declare module 'pollStrings' { + const strings: IPollStrings; + export = strings; +} diff --git a/samples/angular-multipage/src/webparts/poll/tests/Poll.test.ts b/samples/angular-multipage/src/webparts/poll/tests/Poll.test.ts new file mode 100644 index 000000000..41cc9bcf1 --- /dev/null +++ b/samples/angular-multipage/src/webparts/poll/tests/Poll.test.ts @@ -0,0 +1,7 @@ +import * as assert from 'assert'; + +describe('PollWebPart', () => { + it('should do something', () => { + assert.ok(true); + }); +}); diff --git a/samples/angular-multipage/tsconfig.json b/samples/angular-multipage/tsconfig.json new file mode 100644 index 000000000..98c8662a9 --- /dev/null +++ b/samples/angular-multipage/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "jsx": "react", + "declaration": true, + "sourceMap": true + } +} diff --git a/samples/angular-multipage/typings/@ms/odsp-webpack.d.ts b/samples/angular-multipage/typings/@ms/odsp-webpack.d.ts new file mode 100644 index 000000000..f2b3b03df --- /dev/null +++ b/samples/angular-multipage/typings/@ms/odsp-webpack.d.ts @@ -0,0 +1,13 @@ +// Type definitions for webpack in Microsoft ODSP projects +// Project: ODSP-WEBPACK + +/* + * This definition of webpack require overrides all other definitions of require in our toolchain + * Make sure all other definitions of require are commented out e.g. in node.d.ts + */ +declare var require: { + (path: string): any; + (paths: string[], callback: (...modules: any[]) => void): void; + resolve: (id: string) => string; + ensure: (paths: string[], callback: (require: (path: string) => T) => void, path: string) => void; +}; \ No newline at end of file diff --git a/samples/angular-multipage/typings/@ms/odsp.d.ts b/samples/angular-multipage/typings/@ms/odsp.d.ts new file mode 100644 index 000000000..ae3334fe0 --- /dev/null +++ b/samples/angular-multipage/typings/@ms/odsp.d.ts @@ -0,0 +1,10 @@ +// Type definitions for Microsoft ODSP projects +// Project: ODSP + +/// + +/* Global definition for DEBUG builds */ +declare const DEBUG: boolean; + +/* Global definition for UNIT_TEST builds */ +declare const UNIT_TEST: boolean; \ No newline at end of file diff --git a/samples/angular-multipage/typings/assertion-error/assertion-error.d.ts b/samples/angular-multipage/typings/assertion-error/assertion-error.d.ts new file mode 100644 index 000000000..08217c9e5 --- /dev/null +++ b/samples/angular-multipage/typings/assertion-error/assertion-error.d.ts @@ -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 +// 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; +} diff --git a/samples/angular-multipage/typings/chai/chai.d.ts b/samples/angular-multipage/typings/chai/chai.d.ts new file mode 100644 index 000000000..da4d718e1 --- /dev/null +++ b/samples/angular-multipage/typings/chai/chai.d.ts @@ -0,0 +1,388 @@ +// Type definitions for chai 3.2.0 +// Project: http://chaijs.com/ +// Definitions by: Jed Mao , +// Bart van der Schoor , +// Andrew Brown , +// Olivier Chevet +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +// + +declare module Chai { + + interface ChaiStatic { + expect: ExpectStatic; + should(): Should; + /** + * Provides a way to extend the internals of Chai + */ + use(fn: (chai: any, utils: any) => void): any; + assert: AssertStatic; + config: Config; + AssertionError: AssertionError; + } + + export interface ExpectStatic extends AssertionStatic { + fail(actual?: any, expected?: any, message?: string, operator?: string): void; + } + + export interface AssertStatic extends Assert { + } + + export interface AssertionStatic { + (target: any, message?: string): Assertion; + } + + interface ShouldAssertion { + equal(value1: any, value2: any, message?: string): void; + Throw: ShouldThrow; + throw: ShouldThrow; + exist(value: any, message?: string): void; + } + + interface Should extends ShouldAssertion { + not: ShouldAssertion; + fail(actual: any, expected: any, message?: string, operator?: string): void; + } + + interface ShouldThrow { + (actual: Function): void; + (actual: Function, expected: string|RegExp, message?: string): void; + (actual: Function, constructor: Error|Function, expected?: string|RegExp, message?: string): void; + } + + interface Assertion extends LanguageChains, NumericComparison, TypeComparison { + not: Assertion; + deep: Deep; + any: KeyFilter; + all: KeyFilter; + a: TypeComparison; + an: TypeComparison; + include: Include; + includes: Include; + contain: Include; + contains: Include; + ok: Assertion; + true: Assertion; + false: Assertion; + null: Assertion; + undefined: Assertion; + NaN: Assertion; + exist: Assertion; + empty: Assertion; + arguments: Assertion; + Arguments: Assertion; + equal: Equal; + equals: Equal; + eq: Equal; + eql: Equal; + eqls: Equal; + property: Property; + ownProperty: OwnProperty; + haveOwnProperty: OwnProperty; + ownPropertyDescriptor: OwnPropertyDescriptor; + haveOwnPropertyDescriptor: OwnPropertyDescriptor; + length: Length; + lengthOf: Length; + match: Match; + matches: Match; + string(string: string, message?: string): Assertion; + keys: Keys; + key(string: string): Assertion; + throw: Throw; + throws: Throw; + Throw: Throw; + respondTo: RespondTo; + respondsTo: RespondTo; + itself: Assertion; + satisfy: Satisfy; + satisfies: Satisfy; + closeTo(expected: number, delta: number, message?: string): Assertion; + members: Members; + increase: PropertyChange; + increases: PropertyChange; + decrease: PropertyChange; + decreases: PropertyChange; + change: PropertyChange; + changes: PropertyChange; + extensible: Assertion; + sealed: Assertion; + frozen: Assertion; + + } + + interface LanguageChains { + to: Assertion; + be: Assertion; + been: Assertion; + is: Assertion; + that: Assertion; + which: Assertion; + and: Assertion; + has: Assertion; + have: Assertion; + with: Assertion; + at: Assertion; + of: Assertion; + same: Assertion; + } + + interface NumericComparison { + above: NumberComparer; + gt: NumberComparer; + greaterThan: NumberComparer; + least: NumberComparer; + gte: NumberComparer; + below: NumberComparer; + lt: NumberComparer; + lessThan: NumberComparer; + most: NumberComparer; + lte: NumberComparer; + within(start: number, finish: number, message?: string): Assertion; + } + + interface NumberComparer { + (value: number, message?: string): Assertion; + } + + interface TypeComparison { + (type: string, message?: string): Assertion; + instanceof: InstanceOf; + instanceOf: InstanceOf; + } + + interface InstanceOf { + (constructor: Object, message?: string): Assertion; + } + + interface Deep { + equal: Equal; + include: Include; + property: Property; + members: Members; + } + + interface KeyFilter { + keys: Keys; + } + + interface Equal { + (value: any, message?: string): Assertion; + } + + interface Property { + (name: string, value?: any, message?: string): Assertion; + } + + interface OwnProperty { + (name: string, message?: string): Assertion; + } + + interface OwnPropertyDescriptor { + (name: string, descriptor: PropertyDescriptor, message?: string): Assertion; + (name: string, message?: string): Assertion; + } + + interface Length extends LanguageChains, NumericComparison { + (length: number, message?: string): Assertion; + } + + interface Include { + (value: Object, message?: string): Assertion; + (value: string, message?: string): Assertion; + (value: number, message?: string): Assertion; + keys: Keys; + members: Members; + any: KeyFilter; + all: KeyFilter; + } + + interface Match { + (regexp: RegExp|string, message?: string): Assertion; + } + + interface Keys { + (...keys: string[]): Assertion; + (keys: any[]): Assertion; + (keys: Object): Assertion; + } + + interface Throw { + (): Assertion; + (expected: string, message?: string): Assertion; + (expected: RegExp, message?: string): Assertion; + (constructor: Error, expected?: string, message?: string): Assertion; + (constructor: Error, expected?: RegExp, message?: string): Assertion; + (constructor: Function, expected?: string, message?: string): Assertion; + (constructor: Function, expected?: RegExp, message?: string): Assertion; + } + + interface RespondTo { + (method: string, message?: string): Assertion; + } + + interface Satisfy { + (matcher: Function, message?: string): Assertion; + } + + interface Members { + (set: any[], message?: string): Assertion; + } + + interface PropertyChange { + (object: Object, prop: string, msg?: string): Assertion; + } + + export interface Assert { + /** + * @param expression Expression to test for truthiness. + * @param message Message to display on error. + */ + (expression: any, message?: string): void; + + fail(actual?: any, expected?: any, msg?: string, operator?: string): void; + + ok(val: any, msg?: string): void; + isOk(val: any, msg?: string): void; + notOk(val: any, msg?: string): void; + isNotOk(val: any, msg?: string): void; + + equal(act: any, exp: any, msg?: string): void; + notEqual(act: any, exp: any, msg?: string): void; + + strictEqual(act: any, exp: any, msg?: string): void; + notStrictEqual(act: any, exp: any, msg?: string): void; + + deepEqual(act: any, exp: any, msg?: string): void; + notDeepEqual(act: any, exp: any, msg?: string): void; + + isTrue(val: any, msg?: string): void; + isFalse(val: any, msg?: string): void; + + isNull(val: any, msg?: string): void; + isNotNull(val: any, msg?: string): void; + + isUndefined(val: any, msg?: string): void; + isDefined(val: any, msg?: string): void; + + isNaN(val: any, msg?: string): void; + isNotNaN(val: any, msg?: string): void; + + isAbove(val: number, abv: number, msg?: string): void; + isBelow(val: number, blw: number, msg?: string): void; + + isFunction(val: any, msg?: string): void; + isNotFunction(val: any, msg?: string): void; + + isObject(val: any, msg?: string): void; + isNotObject(val: any, msg?: string): void; + + isArray(val: any, msg?: string): void; + isNotArray(val: any, msg?: string): void; + + isString(val: any, msg?: string): void; + isNotString(val: any, msg?: string): void; + + isNumber(val: any, msg?: string): void; + isNotNumber(val: any, msg?: string): void; + + isBoolean(val: any, msg?: string): void; + isNotBoolean(val: any, msg?: string): void; + + typeOf(val: any, type: string, msg?: string): void; + notTypeOf(val: any, type: string, msg?: string): void; + + instanceOf(val: any, type: Function, msg?: string): void; + notInstanceOf(val: any, type: Function, msg?: string): void; + + include(exp: string, inc: any, msg?: string): void; + include(exp: any[], inc: any, msg?: string): void; + + notInclude(exp: string, inc: any, msg?: string): void; + notInclude(exp: any[], inc: any, msg?: string): void; + + match(exp: any, re: RegExp, msg?: string): void; + notMatch(exp: any, re: RegExp, msg?: string): void; + + property(obj: Object, prop: string, msg?: string): void; + notProperty(obj: Object, prop: string, msg?: string): void; + deepProperty(obj: Object, prop: string, msg?: string): void; + notDeepProperty(obj: Object, prop: string, msg?: string): void; + + propertyVal(obj: Object, prop: string, val: any, msg?: string): void; + propertyNotVal(obj: Object, prop: string, val: any, msg?: string): void; + + deepPropertyVal(obj: Object, prop: string, val: any, msg?: string): void; + deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string): void; + + lengthOf(exp: any, len: number, msg?: string): void; + //alias frenzy + throw(fn: Function, msg?: string): void; + throw(fn: Function, regExp: RegExp): void; + throw(fn: Function, errType: Function, msg?: string): void; + throw(fn: Function, errType: Function, regExp: RegExp): void; + + throws(fn: Function, msg?: string): void; + throws(fn: Function, regExp: RegExp): void; + throws(fn: Function, errType: Function, msg?: string): void; + throws(fn: Function, errType: Function, regExp: RegExp): void; + + Throw(fn: Function, msg?: string): void; + Throw(fn: Function, regExp: RegExp): void; + Throw(fn: Function, errType: Function, msg?: string): void; + Throw(fn: Function, errType: Function, regExp: RegExp): void; + + doesNotThrow(fn: Function, msg?: string): void; + doesNotThrow(fn: Function, regExp: RegExp): void; + doesNotThrow(fn: Function, errType: Function, msg?: string): void; + doesNotThrow(fn: Function, errType: Function, regExp: RegExp): void; + + operator(val: any, operator: string, val2: any, msg?: string): void; + closeTo(act: number, exp: number, delta: number, msg?: string): void; + + sameMembers(set1: any[], set2: any[], msg?: string): void; + sameDeepMembers(set1: any[], set2: any[], msg?: string): void; + includeMembers(superset: any[], subset: any[], msg?: string): void; + + ifError(val: any, msg?: string): void; + + isExtensible(obj: {}, msg?: string): void; + extensible(obj: {}, msg?: string): void; + isNotExtensible(obj: {}, msg?: string): void; + notExtensible(obj: {}, msg?: string): void; + + isSealed(obj: {}, msg?: string): void; + sealed(obj: {}, msg?: string): void; + isNotSealed(obj: {}, msg?: string): void; + notSealed(obj: {}, msg?: string): void; + + isFrozen(obj: Object, msg?: string): void; + frozen(obj: Object, msg?: string): void; + isNotFrozen(obj: Object, msg?: string): void; + notFrozen(obj: Object, msg?: string): void; + + + } + + export interface Config { + includeStack: boolean; + } + + export class AssertionError { + constructor(message: string, _props?: any, ssf?: Function); + name: string; + message: string; + showDiff: boolean; + stack: string; + } +} + +declare var chai: Chai.ChaiStatic; + +declare module "chai" { + export = chai; +} + +interface Object { + should: Chai.Assertion; +} diff --git a/samples/angular-multipage/typings/combokeys/combokeys.d.ts b/samples/angular-multipage/typings/combokeys/combokeys.d.ts new file mode 100644 index 000000000..f7e1e5b03 --- /dev/null +++ b/samples/angular-multipage/typings/combokeys/combokeys.d.ts @@ -0,0 +1,107 @@ +// Type definitions for Combokeys v2.4.6 +// Project: https://github.com/PolicyStat/combokeys +// Definitions by: Ian Clanton-Thuon +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare namespace Combokeys { + interface CombokeysStatic { + new (element: Element): Combokeys; + + /** + * all instances of Combokeys + */ + instances: Combokeys[]; + + /** + * reset all instances + */ + reset(): void; + } + + interface Combokeys { + element: Element; + + /** + * binds an event to Combokeys + * + * can be a single key, a combination of keys separated with +, + * an array of keys, or a sequence of keys separated by spaces + * + * be sure to list the modifier keys first to make sure that the + * correct key ends up getting bound (the last key in the pattern) + * + * @param {keys} key combination or combinations + * @param {callback} callback function + * @param {handler} optional - one of "keypress", "keydown", or "keyup" + * @returns void + */ + bind(keys: string | string[], callback: () => void, action?: string): void; + + + /** + * binds multiple combinations to the same callback + * + * @param {keys} key combinations + * @param {callback} callback function + * @param {handler} optional - one of "keypress", "keydown", or "keyup" + * @returns void + */ + bindMultiple(keys: string[], callback: () => void, action?: string): void; + + /** + * unbinds an event to Combokeys + * + * the unbinding sets the callback function of the specified key combo + * to an empty function and deletes the corresponding key in the + * directMap dict. + * + * the keycombo+action has to be exactly the same as + * it was defined in the bind method + * + * @param {keys} key combination or combinations + * @param {action} optional - one of "keypress", "keydown", or "keyup" + * @returns void + */ + unbind(keys: string | string[], action?: string): void; + + /** + * triggers an event that has already been bound + * + * @param {keys} key combination + * @param {action} optional - one of "keypress", "keydown", or "keyup" + * @returns void + */ + trigger(keys: string, action?: string): void; + + /** + * resets the library back to its initial state. This is useful + * if you want to clear out the current keyboard shortcuts and bind + * new ones - for example if you switch to another page + * + * @returns void + */ + reset(): void; + + /** + * should we stop this event before firing off callbacks + * + * @param {e} event + * @param {element} bound element + * @return {boolean} + */ + stopCallback(e: Event, element: Element): boolean; + + /** + * detach all listners from the bound element + * + * @return {void} + */ + detach(): void; + } +} + +declare var combokeys: Combokeys.CombokeysStatic; + +declare module "combokeys" { + export = combokeys; +} diff --git a/samples/angular-multipage/typings/es6-collections/es6-collections.d.ts b/samples/angular-multipage/typings/es6-collections/es6-collections.d.ts new file mode 100644 index 000000000..bc39df295 --- /dev/null +++ b/samples/angular-multipage/typings/es6-collections/es6-collections.d.ts @@ -0,0 +1,113 @@ +// Type definitions for es6-collections v0.5.1 +// Project: https://github.com/WebReflection/es6-collections/ +// Definitions by: Ron Buckton +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/* ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + +interface IteratorResult { + done: boolean; + value?: T; +} + +interface Iterator { + next(value?: any): IteratorResult; + return?(value?: any): IteratorResult; + throw?(e?: any): IteratorResult; +} + +interface ForEachable { + forEach(callbackfn: (value: T) => void): void; +} + +interface Map { + clear(): void; + delete(key: K): boolean; + forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): Map; + entries(): Iterator<[K, V]>; + keys(): Iterator; + values(): Iterator; + size: number; +} + +interface MapConstructor { + new (): Map; + new (iterable: ForEachable<[K, V]>): Map; + prototype: Map; +} + +declare var Map: MapConstructor; + +interface Set { + add(value: T): Set; + clear(): void; + delete(value: T): boolean; + forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; + has(value: T): boolean; + entries(): Iterator<[T, T]>; + keys(): Iterator; + values(): Iterator; + size: number; +} + +interface SetConstructor { + new (): Set; + new (iterable: ForEachable): Set; + prototype: Set; +} + +declare var Set: SetConstructor; + +interface WeakMap { + delete(key: K): boolean; + clear(): void; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): WeakMap; +} + +interface WeakMapConstructor { + new (): WeakMap; + new (iterable: ForEachable<[K, V]>): WeakMap; + prototype: WeakMap; +} + +declare var WeakMap: WeakMapConstructor; + +interface WeakSet { + delete(value: T): boolean; + clear(): void; + add(value: T): WeakSet; + has(value: T): boolean; +} + +interface WeakSetConstructor { + new (): WeakSet; + new (iterable: ForEachable): WeakSet; + prototype: WeakSet; +} + +declare var WeakSet: WeakSetConstructor; + +declare module "es6-collections" { + var Map: MapConstructor; + var Set: SetConstructor; + var WeakMap: WeakMapConstructor; + var WeakSet: WeakSetConstructor; +} \ No newline at end of file diff --git a/samples/angular-multipage/typings/es6-promise/es6-promise.d.ts b/samples/angular-multipage/typings/es6-promise/es6-promise.d.ts new file mode 100644 index 000000000..a8f8d7845 --- /dev/null +++ b/samples/angular-multipage/typings/es6-promise/es6-promise.d.ts @@ -0,0 +1,74 @@ +// Type definitions for es6-promise +// Project: https://github.com/jakearchibald/ES6-Promise +// Definitions by: François de Campredon , vvakame +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +interface Thenable { + then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => U | Thenable): Thenable; + then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => void): Thenable; + catch(onRejected?: (error: any) => U | Thenable): Thenable; +} + +declare class Promise implements Thenable { + /** + * If you call resolve in the body of the callback passed to the constructor, + * your promise is fulfilled with result object passed to resolve. + * If you call reject your promise is rejected with the object passed to reject. + * For consistency and debugging (eg stack traces), obj should be an instanceof Error. + * Any errors thrown in the constructor callback will be implicitly passed to reject(). + */ + constructor(callback: (resolve : (value?: R | Thenable) => void, reject: (error?: any) => void) => void); + + /** + * onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects. + * Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called. + * Both callbacks have a single parameter , the fulfillment value or rejection reason. + * "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve. + * If an error is thrown in the callback, the returned promise rejects with that error. + * + * @param onFulfilled called when/if "promise" resolves + * @param onRejected called when/if "promise" rejects + */ + then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => U | Thenable): Promise; + then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => void): Promise; + + /** + * Sugar for promise.then(undefined, onRejected) + * + * @param onRejected called when/if "promise" rejects + */ + catch(onRejected?: (error: any) => U | Thenable): Promise; +} + +declare module Promise { + /** + * Make a new promise from the thenable. + * A thenable is promise-like in as far as it has a "then" method. + */ + function resolve(value?: R | Thenable): Promise; + + /** + * Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error + */ + function reject(error: any): Promise; + + /** + * Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects. + * the array passed to all can be a mixture of promise-like objects and other objects. + * The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value. + */ + function all(promises: (R | Thenable)[]): Promise; + + /** + * Make a Promise that fulfills when any item fulfills, and rejects if any item rejects. + */ + function race(promises: (R | Thenable)[]): Promise; +} + +declare module 'es6-promise' { + var foo: typeof Promise; // Temp variable to reference Promise in local context + module rsvp { + export var Promise: typeof foo; + } + export = rsvp; +} diff --git a/samples/angular-multipage/typings/knockout/knockout.d.ts b/samples/angular-multipage/typings/knockout/knockout.d.ts new file mode 100644 index 000000000..267f3174c --- /dev/null +++ b/samples/angular-multipage/typings/knockout/knockout.d.ts @@ -0,0 +1,631 @@ +// Type definitions for Knockout v3.2.0 +// Project: http://knockoutjs.com +// Definitions by: Boris Yankov , Igor Oleinikov , Clément Bourgeois +// Definitions: https://github.com/borisyankov/DefinitelyTyped + + +interface KnockoutSubscribableFunctions { + [key: string]: KnockoutBindingHandler; + + notifySubscribers(valueToWrite?: T, event?: string): void; +} + +interface KnockoutComputedFunctions { + [key: string]: KnockoutBindingHandler; +} + +interface KnockoutObservableFunctions { + [key: string]: KnockoutBindingHandler; + + equalityComparer(a: any, b: any): boolean; +} + +interface KnockoutObservableArrayFunctions { + // 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; + sort(): KnockoutObservableArray; + sort(compareFunction: (left: T, right: T) => number): KnockoutObservableArray; + + // 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; + + new (): KnockoutSubscribable; +} + +interface KnockoutSubscription { + dispose(): void; +} + +interface KnockoutSubscribable extends KnockoutSubscribableFunctions { + subscribe(callback: (newValue: T) => void, target?: any, event?: string): KnockoutSubscription; + subscribe(callback: (newValue: TEvent) => void, target: any, event: string): KnockoutSubscription; + extend(requestedExtenders: { [key: string]: any; }): KnockoutSubscribable; + getSubscriptionsCount(): number; +} + +interface KnockoutComputedStatic { + fn: KnockoutComputedFunctions; + + (): KnockoutComputed; + (func: () => T, context?: any, options?: any): KnockoutComputed; + (def: KnockoutComputedDefine, context?: any): KnockoutComputed; +} + +interface KnockoutComputed extends KnockoutObservable, KnockoutComputedFunctions { + fn: KnockoutComputedFunctions; + + dispose(): void; + isActive(): boolean; + getDependenciesCount(): number; + extend(requestedExtenders: { [key: string]: any; }): KnockoutComputed; +} + +interface KnockoutObservableArrayStatic { + fn: KnockoutObservableArrayFunctions; + + (value?: T[]): KnockoutObservableArray; +} + +interface KnockoutObservableArray extends KnockoutObservable, KnockoutObservableArrayFunctions { + extend(requestedExtenders: { [key: string]: any; }): KnockoutObservableArray; +} + +interface KnockoutObservableStatic { + fn: KnockoutObservableFunctions; + + (value?: T): KnockoutObservable; +} + +interface KnockoutObservable extends KnockoutSubscribable, KnockoutObservableFunctions { + (): T; + (value: T): void; + + peek(): T; + valueHasMutated?:{(): void;}; + valueWillMutate?:{(): void;}; + extend(requestedExtenders: { [key: string]: any; }): KnockoutObservable; +} + +interface KnockoutComputedDefine { + 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; + $index?: KnockoutObservable; + $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; + 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; + 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(array: T[] | KnockoutObservable, value: T, included: T): void; + + arrayFilter(array: T[], predicate: (item: T) => boolean): T[]; + + arrayFirst(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T; + + arrayForEach(array: T[], action: (item: T, index: number) => void): void; + + arrayGetDistinctValues(array: T[]): T[]; + + arrayIndexOf(array: T[], item: T): number; + + arrayMap(array: T[], mapping: (item: T) => U): U[]; + + arrayPushAll(array: T[] | KnockoutObservableArray, valuesToPush: T[]): T[]; + + arrayRemoveItem(array: any[], itemToRemove: any): void; + + compareArrays(a: T[], b: T[]): Array>; + + 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(value: KnockoutObservable): 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): void; + + stringifyJson(data: any, replacer?: Function, space?: string): string; + + toggleDomNodeCssClass(node: any, className: string, shouldHaveClass: boolean): void; + + triggerEvent(element: any, eventType: any): void; + + unwrapObservable(value: KnockoutObservable | 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 { + 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(evaluatorFunction: () => T, context?: any): KnockoutComputed; + pureComputed(options: KnockoutComputedDefine, context?: any): KnockoutComputed; + + 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(value: KnockoutObservable | 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, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any; + renderTemplateForEach(template: any, arrayOrObservableArray: KnockoutObservable, 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; +} diff --git a/samples/angular-multipage/typings/lodash/lodash.d.ts b/samples/angular-multipage/typings/lodash/lodash.d.ts new file mode 100644 index 000000000..1e39d223f --- /dev/null +++ b/samples/angular-multipage/typings/lodash/lodash.d.ts @@ -0,0 +1,20808 @@ +// Type definitions for Lo-Dash +// Project: http://lodash.com/ +// Definitions by: Brian Zengel , Ilya Mochalov , Stepan Mikhaylyuk +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + + +/** +### 4.0.0 Changelog (https://github.com/lodash/lodash/wiki/Changelog) + +#### TODO: +removed: +- [x] Removed _.support +- [x] Removed _.findWhere in favor of _.find with iteratee shorthand +- [x] Removed _.where in favor of _.filter with iteratee shorthand +- [x] Removed _.pluck in favor of _.map with iteratee shorthand + +renamed: +- [x] Renamed _.first to _.head +- [x] Renamed _.indexBy to _.keyBy +- [x] Renamed _.invoke to _.invokeMap +- [x] Renamed _.overArgs to _.overArgs +- [x] Renamed _.padLeft & _.padRight to _.padStart & _.padEnd +- [x] Renamed _.pairs to _.toPairs +- [x] Renamed _.rest to _.tail +- [x] Renamed _.restParam to _.rest +- [x] Renamed _.sortByOrder to _.orderBy +- [x] Renamed _.trimLeft & _.trimRight to _.trimStart & _.trimEnd +- [x] Renamed _.trunc to _.truncate + +split: +- [x] Split _.indexOf & _.lastIndexOf into _.sortedIndexOf & _.sortedLastIndexOf +- [x] Split _.max & _.min into _.maxBy & _.minBy +- [x] Split _.omit & _.pick into _.omitBy & _.pickBy +- [x] Split _.sample into _.sampleSize +- [x] Split _.sortedIndex into _.sortedIndexBy +- [x] Split _.sortedLastIndex into _.sortedLastIndexBy +- [x] Split _.uniq into _.sortedUniq, _.sortedUniqBy, & _.uniqBy + +changes: +- [x] Absorbed _.sortByAll into _.sortBy +- [x] Changed the category of _.at to “Object” +- [x] Changed the category of _.bindAll to “Utility” +- [x] Made _.capitalize uppercase the first character & lowercase the rest +- [x] Made _.functions return only own method names + + +added 23 array methods: +- [x] _.concat +- [x] _.differenceBy +- [x] _.differenceWith +- [x] _.flatMap +- [x] _.fromPairs +- [x] _.intersectionBy +- [x] _.intersectionWith +- [x] _.join +- [x] _.pullAll +- [x] _.pullAllBy +- [x] _.reverse +- [x] _.sortedIndexBy +- [x] _.sortedIndexOf +- [x] _.sortedLastIndexBy +- [x] _.sortedLastIndexOf +- [x] _.sortedUniq +- [x] _.sortedUniqBy +- [x] _.unionBy +- [x] _.unionWith +- [x] _.uniqBy +- [x] _.uniqWith +- [x] _.xorBy +- [x] _.xorWith + +added 18 lang methods: +- [x] _.cloneDeepWith +- [x] _.cloneWith +- [x] _.eq +- [x] _.isArrayLike +- [x] _.isArrayLikeObject +- [x] _.isEqualWith +- [x] _.isInteger +- [x] _.isLength +- [x] _.isMatchWith +- [x] _.isNil +- [x] _.isObjectLike +- [x] _.isSafeInteger +- [x] _.isSymbol +- [x] _.toInteger +- [x] _.toLength +- [x] _.toNumber +- [x] _.toSafeInteger +- [x] _.toString + +added 13 object methods: +- [x] _.assignIn +- [x] _.assignInWith +- [x] _.assignWith +- [x] _.functionsIn +- [x] _.hasIn +- [x] _.mergeWith +- [x] _.omitBy +- [x] _.pickBy + + +added 8 string methods: +- [x] _.lowerCase +- [x] _.lowerFirst +- [x] _.upperCase +- [x] _.upperFirst +- [x] _.toLower +- [x] _.toUpper + +added 8 utility methods: +- [x] _.toPath + +added 4 math methods: +- [x] _.maxBy +- [x] _.mean +- [x] _.minBy +- [x] _.sumBy + +added 2 function methods: +- [x] _.flip +- [x] _.unary + +added 2 number methods: +- [x] _.clamp +- [x] _.subtract + +added collection method: +- [x] _.sampleSize + +Added 3 aliases + +- [x] _.first as an alias of _.head + +Removed 17 aliases +- [x] Removed aliase _.all +- [x] Removed aliase _.any +- [x] Removed aliase _.backflow +- [x] Removed aliase _.callback +- [x] Removed aliase _.collect +- [x] Removed aliase _.compose +- [x] Removed aliase _.contains +- [x] Removed aliase _.detect +- [x] Removed aliase _.foldl +- [x] Removed aliase _.foldr +- [x] Removed aliase _.include +- [x] Removed aliase _.inject +- [x] Removed aliase _.methods +- [x] Removed aliase _.object +- [x] Removed aliase _.run +- [x] Removed aliase _.select +- [x] Removed aliase _.unique + +Other changes +- [x] Added support for array buffers to _.isEqual +- [x] Added support for converting iterators to _.toArray +- [x] Added support for deep paths to _.zipObject +- [x] Changed UMD to export to window or self when available regardless of other exports +- [x] Ensured debounce cancel clears args & thisArg references +- [x] Ensured _.add, _.subtract, & _.sum don’t skip NaN values +- [x] Ensured _.clone treats generators like functions +- [x] Ensured _.clone produces clones with the source’s [[Prototype]] +- [x] Ensured _.defaults assigns properties that shadow Object.prototype +- [x] Ensured _.defaultsDeep doesn’t merge a string into an array +- [x] Ensured _.defaultsDeep & _.merge don’t modify sources +- [x] Ensured _.defaultsDeep works with circular references +- [x] Ensured _.keys skips “length” on strict mode arguments objects in Safari 9 +- [x] Ensured _.merge doesn’t convert strings to arrays +- [x] Ensured _.merge merges plain-objects onto non plain-objects +- [x] Ensured _#plant resets iterator data of cloned sequences +- [x] Ensured _.random swaps min & max if min is greater than max +- [x] Ensured _.range preserves the sign of start of -0 +- [x] Ensured _.reduce & _.reduceRight use getIteratee in their array branch +- [x] Fixed rounding issue with the precision param of _.floor + +** LATER ** +Misc: +- [ ] Made _.forEach, _.forIn, _.forOwn, & _.times implicitly end a chain sequence +- [ ] Removed thisArg params from most methods +- [ ] Made “By” methods provide a single param to iteratees +- [ ] Made _.words chainable by default +- [ ] Removed isDeep params from _.clone & _.flatten +- [ ] Removed _.bindAll support for binding all methods when no names are provided +- [ ] Removed func-first param signature from _.before & _.after +- [ ] _.extend as an alias of _.assignIn +- [ ] _.extendWith as an alias of _.assignInWith +- [ ] Added clear method to _.memoize.Cache +- [ ] Added flush method to debounced & throttled functions +- [ ] Added support for ES6 maps, sets, & symbols to _.clone, _.isEqual, & _.toArray +- [ ] Enabled _.flow & _.flowRight to accept an array of functions +- [ ] Ensured “Collection” methods treat functions as objects +- [ ] Ensured _.assign, _.defaults, & _.merge coerce object values to objects +- [ ] Ensured _.bindKey bound functions call object[key] when called with the new operator +- [ ] Ensured _.isFunction returns true for generator functions +- [ ] Ensured _.merge assigns typed arrays directly +- [ ] Made _(...) an iterator & iterable +- [ ] Made _.drop, _.take, & right forms coerce n of undefined to 0 + +Methods: +- [ ] _.concat +- [ ] _.differenceBy +- [ ] _.differenceWith +- [ ] _.flatMap +- [ ] _.fromPairs +- [ ] _.intersectionBy +- [ ] _.intersectionWith +- [ ] _.join +- [ ] _.pullAll +- [ ] _.pullAllBy +- [ ] _.reverse +- [ ] _.sortedLastIndexOf +- [ ] _.unionBy +- [ ] _.unionWith +- [ ] _.uniqWith +- [ ] _.xorBy +- [ ] _.xorWith +- [ ] _.toString + +- [ ] _.invoke +- [ ] _.setWith +- [ ] _.toPairs +- [ ] _.toPairsIn +- [ ] _.unset + +- [ ] _.replace +- [ ] _.split + +- [ ] _.cond +- [ ] _.conforms +- [ ] _.nthArg +- [ ] _.over +- [ ] _.overEvery +- [ ] _.overSome +- [ ] _.rangeRight + +- [ ] _.next +*/ + +declare var _: _.LoDashStatic; + +declare module _ { + interface LoDashStatic { + /** + * Creates a lodash object which wraps the given value to enable intuitive method chaining. + * + * In addition to Lo-Dash methods, wrappers also have the following Array methods: + * concat, join, pop, push, reverse, shift, slice, sort, splice, and unshift + * + * Chaining is supported in custom builds as long as the value method is implicitly or + * explicitly included in the build. + * + * The chainable wrapper functions are: + * after, assign, bind, bindAll, bindKey, chain, chunk, compact, compose, concat, countBy, + * createCallback, curry, debounce, defaults, defer, delay, difference, filter, flatten, + * forEach, forEachRight, forIn, forInRight, forOwn, forOwnRight, functions, groupBy, + * keyBy, initial, intersection, invert, invoke, keys, map, max, memoize, merge, min, + * object, omit, once, pairs, partial, partialRight, pick, pluck, pull, push, range, reject, + * remove, rest, reverse, sample, shuffle, slice, sort, sortBy, splice, tap, throttle, times, + * toArray, transform, union, uniq, unset, unshift, unzip, values, where, without, wrap, and zip + * + * The non-chainable wrapper functions are: + * clone, cloneDeep, contains, escape, every, find, findIndex, findKey, findLast, + * findLastIndex, findLastKey, has, identity, indexOf, isArguments, isArray, isBoolean, + * isDate, isElement, isEmpty, isEqual, isFinite, isFunction, isNaN, isNull, isNumber, + * isObject, isPlainObject, isRegExp, isString, isUndefined, join, lastIndexOf, mixin, + * noConflict, parseInt, pop, random, reduce, reduceRight, result, shift, size, some, + * sortedIndex, runInContext, template, unescape, uniqueId, and value + * + * The wrapper functions first and last return wrapped values when n is provided, otherwise + * they return unwrapped values. + * + * Explicit chaining can be enabled by using the _.chain method. + **/ + (value: number): LoDashImplicitWrapper; + (value: string): LoDashImplicitStringWrapper; + (value: boolean): LoDashImplicitWrapper; + (value: Array): LoDashImplicitNumberArrayWrapper; + (value: Array): LoDashImplicitArrayWrapper; + (value: T): LoDashImplicitObjectWrapper; + (value: any): LoDashImplicitWrapper; + + /** + * The semantic version number. + **/ + VERSION: string; + + /** + * By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby + * (ERB). Change the following template settings to use alternative delimiters. + **/ + templateSettings: TemplateSettings; + } + + /** + * By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby + * (ERB). Change the following template settings to use alternative delimiters. + **/ + interface TemplateSettings { + /** + * The "escape" delimiter. + **/ + escape?: RegExp; + + /** + * The "evaluate" delimiter. + **/ + evaluate?: RegExp; + + /** + * An object to import into the template as local variables. + **/ + imports?: Dictionary; + + /** + * The "interpolate" delimiter. + **/ + interpolate?: RegExp; + + /** + * Used to reference the data object in the template text. + **/ + variable?: string; + } + + /** + * Creates a cache object to store key/value pairs. + */ + interface MapCache { + /** + * Removes `key` and its value from the cache. + * @param key The key of the value to remove. + * @return Returns `true` if the entry was removed successfully, else `false`. + */ + delete(key: string): boolean; + + /** + * Gets the cached value for `key`. + * @param key The key of the value to get. + * @return Returns the cached value. + */ + get(key: string): any; + + /** + * Checks if a cached value for `key` exists. + * @param key The key of the entry to check. + * @return Returns `true` if an entry for `key` exists, else `false`. + */ + has(key: string): boolean; + + /** + * Sets `value` to `key` of the cache. + * @param key The key of the value to cache. + * @param value The value to cache. + * @return Returns the cache object. + */ + set(key: string, value: any): _.Dictionary; + } + + interface LoDashWrapperBase { } + + interface LoDashImplicitWrapperBase extends LoDashWrapperBase { } + + interface LoDashExplicitWrapperBase extends LoDashWrapperBase { } + + interface LoDashImplicitWrapper extends LoDashImplicitWrapperBase> { } + + interface LoDashExplicitWrapper extends LoDashExplicitWrapperBase> { } + + interface LoDashImplicitStringWrapper extends LoDashImplicitWrapper { } + + interface LoDashExplicitStringWrapper extends LoDashExplicitWrapper { } + + interface LoDashImplicitObjectWrapper extends LoDashImplicitWrapperBase> { } + + interface LoDashExplicitObjectWrapper extends LoDashExplicitWrapperBase> { } + + interface LoDashImplicitArrayWrapper extends LoDashImplicitWrapperBase> { + pop(): T; + push(...items: T[]): LoDashImplicitArrayWrapper; + shift(): T; + sort(compareFn?: (a: T, b: T) => number): LoDashImplicitArrayWrapper; + splice(start: number): LoDashImplicitArrayWrapper; + splice(start: number, deleteCount: number, ...items: any[]): LoDashImplicitArrayWrapper; + unshift(...items: T[]): LoDashImplicitArrayWrapper; + } + + interface LoDashExplicitArrayWrapper extends LoDashExplicitWrapperBase> { } + + interface LoDashImplicitNumberArrayWrapper extends LoDashImplicitArrayWrapper { } + + interface LoDashExplicitNumberArrayWrapper extends LoDashExplicitArrayWrapper { } + + /********* + * Array * + *********/ + + //_.chunk + interface LoDashStatic { + /** + * Creates an array of elements split into groups the length of size. If collection can’t be split evenly, the + * final chunk will be the remaining elements. + * + * @param array The array to process. + * @param size The length of each chunk. + * @return Returns the new array containing chunks. + */ + chunk( + array: List, + size?: number + ): T[][]; + } + + interface LoDashImplicitArrayWrapper { + /** + * @see _.chunk + */ + chunk(size?: number): LoDashImplicitArrayWrapper; + } + + interface LoDashImplicitObjectWrapper { + /** + * @see _.chunk + */ + chunk(size?: number): LoDashImplicitArrayWrapper; + } + + interface LoDashExplicitArrayWrapper { + /** + * @see _.chunk + */ + chunk(size?: number): LoDashExplicitArrayWrapper; + } + + interface LoDashExplicitObjectWrapper { + /** + * @see _.chunk + */ + chunk(size?: number): LoDashExplicitArrayWrapper; + } + + //_.compact + interface LoDashStatic { + /** + * Creates an array with all falsey values removed. The values false, null, 0, "", undefined, and NaN are + * falsey. + * + * @param array The array to compact. + * @return (Array) Returns the new array of filtered values. + */ + compact(array?: List): T[]; + } + + interface LoDashImplicitArrayWrapper { + /** + * @see _.compact + */ + compact(): LoDashImplicitArrayWrapper; + } + + interface LoDashImplicitObjectWrapper { + /** + * @see _.compact + */ + compact(): LoDashImplicitArrayWrapper; + } + + interface LoDashExplicitArrayWrapper { + /** + * @see _.compact + */ + compact(): LoDashExplicitArrayWrapper; + } + + interface LoDashExplicitObjectWrapper { + /** + * @see _.compact + */ + compact(): LoDashExplicitArrayWrapper; + } + + //_.concat DUMMY + interface LoDashStatic { + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + concat(...values: (T[]|List)[]) : T[]; + } + + //_.difference + interface LoDashStatic { + /** + * Creates an array of unique array values not included in the other provided arrays using SameValueZero for + * equality comparisons. + * + * @param array The array to inspect. + * @param values The arrays of values to exclude. + * @return Returns the new array of filtered values. + */ + difference( + array: T[]|List, + ...values: Array> + ): T[]; + } + + interface LoDashImplicitArrayWrapper { + /** + * @see _.difference + */ + difference(...values: (T[]|List)[]): LoDashImplicitArrayWrapper; + } + + interface LoDashImplicitObjectWrapper