<commit_before>// (C) Copyright 2015 Martin Dougiamas
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

describe('User can change App settings', function() {

    it('User can click settings page tabs', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('General');
        }).then(function() {
           return MM.goBack();
        }).then(function () {
           return MM.clickOn('Space usage');
        }).then(function() {
            return MM.goBack();
        }).then(function () {
           return MM.clickOn('Synchronization');
        }).then(function() {
            return MM.goBack();
        }).then(function() {
            return MM.clickOn('About');
        }).then(function() {
            return MM.goBack();
        }).then(function () {
            done();
        });
    });

    /*it('Change general settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOnElement($('[mm-split-view-link="site.mm_settings-general"]'));
        /*}).then(function () {
            browser.sleep(10000);
            return element(by.model('selectedLanguage')).click();
        }).then(function () {
            return element(by.xpath('/html/body/ion-nav-view/ion-side-menus/ion-side-menu-content/ion-nav-view/ion-view[3]/ion-content/div[1]/ul/li[1]/select/option[9]')).click();
        }).then(function () {
            browser.sleep(10000);
            return element(by.model('selectedLanguage')).click();
        }).then(function () {
            return element(by.xpath('/html/body/ion-nav-view/ion-side-menus/ion-side-menu-content/ion-nav-view/ion-view[2]/ion-content/div[1]/ul/li[1]/select/option[7]')).click();*/
        /*}).then(function () {
            return MM.clickOnElement($('input[ng-model="richTextEditor"]'));
        }).then(function() {
            return MM.clickOnElement($('input[ng-model="richTextEditor"]'));
        }).then(function() {
            return MM.clickOnElement($('input[ng-model="reportInBackground"]'));
        }).then(function() {
            return MM.clickOnElement($('input[ng-model="reportInBackground"]'));
        }).then(function() {
            done();
        });
    });*/

    it('Change Space usage settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('Space usage');
        }).then(function() {
            return MM.goBack();
        }).then(function() {
            done();
        });
    });

    /*it('Change Synchronization settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('Synchronization');
        }).then(function () {
            MM.clickOnElement($('button[ng-click="synchronize(site.id)"]'));
            return expect(element.all(by.css('ion-spinner[ng-if="site.synchronizing"]')).isDisplayed()).toBeTruthy();
        }).then(function(){
            return MM.clickOnElement($('input[type="checkbox"]'));
        }).then(function() {
            done();
        });
    });*/

    it('Change About settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('About');
        }).then(function () {
            expect(MM.getView().getText()).toMatch('Moodle Mobile 3.3.1');
            return MM.goBack();
        }).then(function(){
            done();
        });
    });

});

<commit_msg>MOBILE-2128 e2e: Updated settings.spec.js<commit_after>// (C) Copyright 2015 Martin Dougiamas
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

describe('User can change App settings', function() {

    it('User can click settings page tabs', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('General');
        }).then(function() {
           return MM.goBack();
        }).then(function () {
           return MM.clickOn('Space usage');
        }).then(function() {
            return MM.goBack();
        }).then(function () {
           return MM.clickOn('Synchronization');
        }).then(function() {
            return MM.goBack();
        }).then(function() {
            return MM.clickOn('About');
        }).then(function() {
            return MM.goBack();
        }).then(function () {
            done();
        });
    });

    it('Change general settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOnElement($('[mm-split-view-link="site.mm_settings-general"]'));
        }).then(function () {
            browser.sleep(10000);
            return element(by.model('selectedLanguage')).click();
        }).then(function () {
            return MM.clickOnElement($('option[value="string:de"]'));
        }).then(function () {
            browser.sleep(10000);
            return element(by.model('selectedLanguage')).click();
        }).then(function () {
            return MM.clickOnElement($('option[value="string:en"]'));
        }).then(function () {
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function() {
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function() {
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(1));
        }).then(function() {
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(1));
        }).then(function() {
            done();
        });
    });

    it('Change Space usage settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('Space usage');
        }).then(function() {
            return MM.goBack();
        }).then(function() {
            done();
        });
    });

    it('Change Synchronization settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('Synchronization');
        }).then(function () {
            MM.clickOnElement($('button[ng-click="synchronize(site.id)"]'));
            return expect(element.all(by.css('ion-spinner[ng-if="site.synchronizing"]')).isDisplayed()).toBeTruthy();
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function() {
            done();
        });
    });

    it('Change Notification preferences', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('Notification preferences');
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(1));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(1));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(2));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(2));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(3));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(3));
        }).then(function() {
            done();
        });
    });

    it('Change Message preferences', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('Message preferences');
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(1));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(1));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function(){
            return MM.clickOnElement(element.all(by.css('label[class="toggle disable-user-behavior"]')).get(0));
        }).then(function() {
            done();
        });
    });

    it('Change About settings', function (done) {
        return MM.loginAsStudent().then(function () {
            return MM.clickOnInSideMenu('App settings');
        }).then(function () {
            return MM.clickOn('About');
        }).then(function () {
            expect(MM.getView().getText()).toContain('Moodle Mobile 3.3');
            return MM.goBack();
        }).then(function () {
            done();
        });
    });

});

<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2020 The Stdlib Authors.
*
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name dapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dapxsum}
*/
setReadOnly( ns, 'dapxsum', require( '@stdlib/blas/ext/base/dapxsum' ) );

/**
* @name dapxsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dapxsumpw}
*/
setReadOnly( ns, 'dapxsumpw', require( '@stdlib/blas/ext/base/dapxsumpw' ) );

/**
* @name dasumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dasumpw}
*/
setReadOnly( ns, 'dasumpw', require( '@stdlib/blas/ext/base/dasumpw' ) );

/**
* @name dnanasum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnanasum}
*/
setReadOnly( ns, 'dnanasum', require( '@stdlib/blas/ext/base/dnanasum' ) );

/**
* @name dnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansum}
*/
setReadOnly( ns, 'dnansum', require( '@stdlib/blas/ext/base/dnansum' ) );

/**
* @name dnansumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansumkbn2}
*/
setReadOnly( ns, 'dnansumkbn2', require( '@stdlib/blas/ext/base/dnansumkbn2' ) );

/**
* @name dnansumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansumors}
*/
setReadOnly( ns, 'dnansumors', require( '@stdlib/blas/ext/base/dnansumors' ) );

/**
* @name dnansumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansumpw}
*/
setReadOnly( ns, 'dnansumpw', require( '@stdlib/blas/ext/base/dnansumpw' ) );

/**
* @name dsapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsapxsum}
*/
setReadOnly( ns, 'dsapxsum', require( '@stdlib/blas/ext/base/dsapxsum' ) );

/**
* @name dsnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsnansum}
*/
setReadOnly( ns, 'dsnansum', require( '@stdlib/blas/ext/base/dsnansum' ) );

/**
* @name dssum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dssum}
*/
setReadOnly( ns, 'dssum', require( '@stdlib/blas/ext/base/dssum' ) );

/**
* @name dsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsum}
*/
setReadOnly( ns, 'dsum', require( '@stdlib/blas/ext/base/dsum' ) );

/**
* @name dsumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsumkbn2}
*/
setReadOnly( ns, 'dsumkbn2', require( '@stdlib/blas/ext/base/dsumkbn2' ) );

/**
* @name dsumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsumors}
*/
setReadOnly( ns, 'dsumors', require( '@stdlib/blas/ext/base/dsumors' ) );

/**
* @name dsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsumpw}
*/
setReadOnly( ns, 'dsumpw', require( '@stdlib/blas/ext/base/dsumpw' ) );

/**
* @name gapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gapxsum}
*/
setReadOnly( ns, 'gapxsum', require( '@stdlib/blas/ext/base/gapxsum' ) );

/**
* @name gapxsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gapxsumpw}
*/
setReadOnly( ns, 'gapxsumpw', require( '@stdlib/blas/ext/base/gapxsumpw' ) );

/**
* @name gnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansum}
*/
setReadOnly( ns, 'gnansum', require( '@stdlib/blas/ext/base/gnansum' ) );

/**
* @name gnansumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansumkbn2}
*/
setReadOnly( ns, 'gnansumkbn2', require( '@stdlib/blas/ext/base/gnansumkbn2' ) );

/**
* @name gnansumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansumors}
*/
setReadOnly( ns, 'gnansumors', require( '@stdlib/blas/ext/base/gnansumors' ) );

/**
* @name gnansumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansumpw}
*/
setReadOnly( ns, 'gnansumpw', require( '@stdlib/blas/ext/base/gnansumpw' ) );

/**
* @name gsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsum}
*/
setReadOnly( ns, 'gsum', require( '@stdlib/blas/ext/base/gsum' ) );

/**
* @name gsumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsumkbn2}
*/
setReadOnly( ns, 'gsumkbn2', require( '@stdlib/blas/ext/base/gsumkbn2' ) );

/**
* @name gsumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsumors}
*/
setReadOnly( ns, 'gsumors', require( '@stdlib/blas/ext/base/gsumors' ) );

/**
* @name gsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsumpw}
*/
setReadOnly( ns, 'gsumpw', require( '@stdlib/blas/ext/base/gsumpw' ) );

/**
* @name sapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sapxsum}
*/
setReadOnly( ns, 'sapxsum', require( '@stdlib/blas/ext/base/sapxsum' ) );

/**
* @name sapxsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sapxsumpw}
*/
setReadOnly( ns, 'sapxsumpw', require( '@stdlib/blas/ext/base/sapxsumpw' ) );

/**
* @name sdsapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sdsapxsum}
*/
setReadOnly( ns, 'sdsapxsum', require( '@stdlib/blas/ext/base/sdsapxsum' ) );

/**
* @name sdsnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sdsnansum}
*/
setReadOnly( ns, 'sdsnansum', require( '@stdlib/blas/ext/base/sdsnansum' ) );

/**
* @name sdssum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sdssum}
*/
setReadOnly( ns, 'sdssum', require( '@stdlib/blas/ext/base/sdssum' ) );

/**
* @name snansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansum}
*/
setReadOnly( ns, 'snansum', require( '@stdlib/blas/ext/base/snansum' ) );

/**
* @name snansumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansumkbn2}
*/
setReadOnly( ns, 'snansumkbn2', require( '@stdlib/blas/ext/base/snansumkbn2' ) );

/**
* @name snansumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansumors}
*/
setReadOnly( ns, 'snansumors', require( '@stdlib/blas/ext/base/snansumors' ) );

/**
* @name snansumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansumpw}
*/
setReadOnly( ns, 'snansumpw', require( '@stdlib/blas/ext/base/snansumpw' ) );

/**
* @name ssum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssum}
*/
setReadOnly( ns, 'ssum', require( '@stdlib/blas/ext/base/ssum' ) );

/**
* @name ssumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssumkbn2}
*/
setReadOnly( ns, 'ssumkbn2', require( '@stdlib/blas/ext/base/ssumkbn2' ) );

/**
* @name ssumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssumors}
*/
setReadOnly( ns, 'ssumors', require( '@stdlib/blas/ext/base/ssumors' ) );

/**
* @name ssumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssumpw}
*/
setReadOnly( ns, 'ssumpw', require( '@stdlib/blas/ext/base/ssumpw' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Update namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2020 The Stdlib Authors.
*
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name dapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dapxsum}
*/
setReadOnly( ns, 'dapxsum', require( '@stdlib/blas/ext/base/dapxsum' ) );

/**
* @name dapxsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dapxsumpw}
*/
setReadOnly( ns, 'dapxsumpw', require( '@stdlib/blas/ext/base/dapxsumpw' ) );

/**
* @name dasumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dasumpw}
*/
setReadOnly( ns, 'dasumpw', require( '@stdlib/blas/ext/base/dasumpw' ) );

/**
* @name dnanasum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnanasum}
*/
setReadOnly( ns, 'dnanasum', require( '@stdlib/blas/ext/base/dnanasum' ) );

/**
* @name dnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansum}
*/
setReadOnly( ns, 'dnansum', require( '@stdlib/blas/ext/base/dnansum' ) );

/**
* @name dnansumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansumkbn2}
*/
setReadOnly( ns, 'dnansumkbn2', require( '@stdlib/blas/ext/base/dnansumkbn2' ) );

/**
* @name dnansumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansumors}
*/
setReadOnly( ns, 'dnansumors', require( '@stdlib/blas/ext/base/dnansumors' ) );

/**
* @name dnansumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dnansumpw}
*/
setReadOnly( ns, 'dnansumpw', require( '@stdlib/blas/ext/base/dnansumpw' ) );

/**
* @name dsapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsapxsum}
*/
setReadOnly( ns, 'dsapxsum', require( '@stdlib/blas/ext/base/dsapxsum' ) );

/**
* @name dsnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsnansum}
*/
setReadOnly( ns, 'dsnansum', require( '@stdlib/blas/ext/base/dsnansum' ) );

/**
* @name dssum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dssum}
*/
setReadOnly( ns, 'dssum', require( '@stdlib/blas/ext/base/dssum' ) );

/**
* @name dssumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dssumors}
*/
setReadOnly( ns, 'dssumors', require( '@stdlib/blas/ext/base/dssumors' ) );

/**
* @name dsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsum}
*/
setReadOnly( ns, 'dsum', require( '@stdlib/blas/ext/base/dsum' ) );

/**
* @name dsumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsumkbn2}
*/
setReadOnly( ns, 'dsumkbn2', require( '@stdlib/blas/ext/base/dsumkbn2' ) );

/**
* @name dsumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsumors}
*/
setReadOnly( ns, 'dsumors', require( '@stdlib/blas/ext/base/dsumors' ) );

/**
* @name dsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/dsumpw}
*/
setReadOnly( ns, 'dsumpw', require( '@stdlib/blas/ext/base/dsumpw' ) );

/**
* @name gapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gapxsum}
*/
setReadOnly( ns, 'gapxsum', require( '@stdlib/blas/ext/base/gapxsum' ) );

/**
* @name gapxsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gapxsumpw}
*/
setReadOnly( ns, 'gapxsumpw', require( '@stdlib/blas/ext/base/gapxsumpw' ) );

/**
* @name gnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansum}
*/
setReadOnly( ns, 'gnansum', require( '@stdlib/blas/ext/base/gnansum' ) );

/**
* @name gnansumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansumkbn2}
*/
setReadOnly( ns, 'gnansumkbn2', require( '@stdlib/blas/ext/base/gnansumkbn2' ) );

/**
* @name gnansumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansumors}
*/
setReadOnly( ns, 'gnansumors', require( '@stdlib/blas/ext/base/gnansumors' ) );

/**
* @name gnansumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gnansumpw}
*/
setReadOnly( ns, 'gnansumpw', require( '@stdlib/blas/ext/base/gnansumpw' ) );

/**
* @name gsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsum}
*/
setReadOnly( ns, 'gsum', require( '@stdlib/blas/ext/base/gsum' ) );

/**
* @name gsumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsumkbn2}
*/
setReadOnly( ns, 'gsumkbn2', require( '@stdlib/blas/ext/base/gsumkbn2' ) );

/**
* @name gsumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsumors}
*/
setReadOnly( ns, 'gsumors', require( '@stdlib/blas/ext/base/gsumors' ) );

/**
* @name gsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/gsumpw}
*/
setReadOnly( ns, 'gsumpw', require( '@stdlib/blas/ext/base/gsumpw' ) );

/**
* @name sapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sapxsum}
*/
setReadOnly( ns, 'sapxsum', require( '@stdlib/blas/ext/base/sapxsum' ) );

/**
* @name sapxsumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sapxsumpw}
*/
setReadOnly( ns, 'sapxsumpw', require( '@stdlib/blas/ext/base/sapxsumpw' ) );

/**
* @name sdsapxsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sdsapxsum}
*/
setReadOnly( ns, 'sdsapxsum', require( '@stdlib/blas/ext/base/sdsapxsum' ) );

/**
* @name sdsnansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sdsnansum}
*/
setReadOnly( ns, 'sdsnansum', require( '@stdlib/blas/ext/base/sdsnansum' ) );

/**
* @name sdssum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/sdssum}
*/
setReadOnly( ns, 'sdssum', require( '@stdlib/blas/ext/base/sdssum' ) );

/**
* @name snansum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansum}
*/
setReadOnly( ns, 'snansum', require( '@stdlib/blas/ext/base/snansum' ) );

/**
* @name snansumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansumkbn2}
*/
setReadOnly( ns, 'snansumkbn2', require( '@stdlib/blas/ext/base/snansumkbn2' ) );

/**
* @name snansumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansumors}
*/
setReadOnly( ns, 'snansumors', require( '@stdlib/blas/ext/base/snansumors' ) );

/**
* @name snansumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/snansumpw}
*/
setReadOnly( ns, 'snansumpw', require( '@stdlib/blas/ext/base/snansumpw' ) );

/**
* @name ssum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssum}
*/
setReadOnly( ns, 'ssum', require( '@stdlib/blas/ext/base/ssum' ) );

/**
* @name ssumkbn2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssumkbn2}
*/
setReadOnly( ns, 'ssumkbn2', require( '@stdlib/blas/ext/base/ssumkbn2' ) );

/**
* @name ssumors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssumors}
*/
setReadOnly( ns, 'ssumors', require( '@stdlib/blas/ext/base/ssumors' ) );

/**
* @name ssumpw
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/blas/ext/base/ssumpw}
*/
setReadOnly( ns, 'ssumpw', require( '@stdlib/blas/ext/base/ssumpw' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>var Base = require('./base')
var inherits = require('inherits')
var classes = require('dom-classes')
var domify = require('domify')
var clickdrag = require('clickdrag')
var events = require('dom-events')
var keycode = require('keycode')
var getMouseOffset = require('mouse-event-offset')
var xtend = require('xtend')

var NumberEditors = require('./dom/number-editors')
var createTimeline = require('./dom/create-timeline')
var SelectBox = require('./dom/select-box')
var eases = require('eases')

var noop = function() { return null }

var SCALE = 100

function Editor() {
	if (!(this instanceof Editor))
		return new Editor()

	Base.call(this)

	this.defaultConstraint = { decimals: 1 }
	this.easings = Object.keys(eases)
	this.easings = this.easings.filter(function(e) {
		return 'linear'
	})
	this.easings.unshift({ disabled: true, name: '—' })
	this.easings.unshift('linear')

	this.constraints = {}
	this.editors = {}
	this.shyNames = []
	this.keyEvents = true
	// this.editable = true

    this.element = domify('
')
    this.leftPanel = domify('
')
    this.rightPanel = domify('
')
    this.element.appendChild(this.leftPanel)
    this.element.appendChild(this.rightPanel)

    this.playheadElement = domify('
')
    this.rightPanel.appendChild(this.playheadElement)

    this.on('playhead', handlePlayhead.bind(this))
    this.on('keyframe-toggle', this._toggleKeyframe.bind(this))
    this.on('keyframe-next', keyframeNext.bind(this, true))
    this.on('keyframe-previous', keyframeNext.bind(this, false))
    this.on('keyframe-remove', this._removeKeyframe.bind(this))

    this.on('load', handlePlayhead.bind(this))
    this.on('load', this._updateShyLayers.bind(this))

    events.on(document, 'keydown', handleKey.bind(this), false)
    this.currentEditor = null

    this.draggable = clickdrag(this.rightPanel)
    this.propertyDrag = null
    this.draggable.on('start', this._onDragStart.bind(this))
    this.draggable.on('move', this._onDrag.bind(this))
    this.draggable.on('end', onDragEnd.bind(this))
    this.draggingKeyframe = null

    this.highlightProperty = null
    this.on('highlight-property', function(prop) {
    	if (this.highlightProperty && prop !== this.highlightProperty) {
    		var old = this.highlightProperty
    		classes.remove(old.element, 'highlight')
    		classes.remove(old.animationElement, 'highlight')
    	}
    	this.highlightProperty = prop
    	classes.add(prop.element, 'highlight')
    	classes.add(prop.animationElement, 'highlight')
    }.bind(this))

    this.on('select-easing', function(propertyData) {
    	var ease = propertyData.easingBox.selected()
    	if (propertyData.currentKeyframe) {
    		propertyData.currentKeyframe.ease = ease
    	} else {
    		var keyframes = propertyData.property.keyframes
    		var next = keyframes.next( this.playhead() )
    		if (next)
    			next.ease = ease
    	}
    }.bind(this))

}

inherits(Editor, Base)

function handleKey(ev) {
	if (!this.keyEvents)
		return

	var key = keycode(ev)
	if (key === 'left') {
		if (this.currentEditor && this.currentEditor.editing)
			return

		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-previous', this.highlightProperty)
	} else if (key === 'right') {
		if (this.currentEditor && this.currentEditor.editing)
			return

		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-next', this.highlightProperty)
	} else if (key === 'k') {
		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-toggle', this.highlightProperty.timelineData, this.highlightProperty)
	} else if (key === 'delete' || key === 'backspace') {
		if (this.currentEditor && this.currentEditor.editing)
			return

		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-remove', this.highlightProperty.timelineData, this.highlightProperty)
	}
}

function keyframeNext(goNext, propertyData) {
	var keyframes = propertyData.property.keyframes
	var time = this.playhead()
    var next = goNext ? keyframes.next(time) : keyframes.previous(time)
    if (next) {
        this.playhead(next.time)
    }
}

Editor.prototype._onDragStart = function(ev, offset, delta) {
	if (this.draggingKeyframe)
		this.propertyDrag = this.draggingKeyframe.element.parentNode
	else
		this.propertyDrag = ev.target
	this._onDrag(ev, offset, delta)
}

Editor.prototype._onDrag = function(ev, offset, delta) {
	ev.preventDefault()

	if (!this.propertyDrag)
		return

	var rect = this.propertyDrag.getBoundingClientRect()
    offset = getMouseOffset(ev, { clientRect: rect })
    offset.x = Math.max(0, offset.x)

	if (this.draggingKeyframe) {
		this.draggingKeyframe.element.style.left = Math.round(offset.x)+'px'
		this.draggingKeyframe.keyframe.time = offset.x/SCALE
		this.draggingKeyframe.propertyData.updateKeyframes()
		this._updateProperties()
	} else {
		this.playhead(offset.x / SCALE)
	}
}

function onDragEnd(ev, offset, delta) {
	this.draggingKeyframe = null
	this.propertyDrag = null
}

function handlePlayhead(time) {
	this.playheadElement.style.left = Math.round(time*SCALE)+'px'
	this._updateProperties()
}

//Creates a new timeline object which has { element, open, name, dispose }
Editor.prototype._createTimeline = function(timeline, name) {
	return createTimeline(this, timeline, name)
}

Editor.prototype._updateProperties = function() {
    var curTime = this.playhead()
    this.timelinesData.forEach(function(tData) {
    	var timeline = tData.timeline

        tData.propertyData.forEach(function(propData) {
        	var prop = propData.property
			var curVal = timeline.valueOf(curTime, prop)
			propData.updateEditor(curVal)

            var highlightIdx = prop.keyframes.getIndex(curTime)
            var highlight = prop.keyframes.frames[highlightIdx]

            propData.keyframeData.forEach(function(k) {
            	classes.remove(k.element, 'highlight')
            	if (k.keyframe===highlight) {
	                classes.add(k.element, 'highlight')
	            }
            })

            var nextFrame = highlight || prop.keyframes.next(curTime)
            var curEase = nextFrame
            var hasEasing = nextFrame && nextFrame !== prop.keyframes.frames[0]

            classes.remove(propData.element, 'has-easing')
            if (hasEasing)
            	classes.add(propData.element, 'has-easing')

            if (propData.easingBox) {
            	var box = propData.easingBox.element
            	if (hasEasing) {
	            	box.removeAttribute('disabled')
	            	propData.easingBox.select(curEase.ease || 'linear')
	            } else
	            	box.setAttribute('disabled', 'disabled')
	        }
            propData.currentKeyframe = highlight
        })
    })
	this.emit('update')
}

Editor.prototype.createEasingSelect = function(options) {
	return new SelectBox(xtend(options||{}, { data: this.easings }))
}

Editor.prototype.valueEditor = function(name, func) {
	if (!func)
		this.editors[name] = undefined
	else
		this.editors[name] = func
	return this
}

Editor.prototype.createValueEditor = function(timeline, property) {
	var value = timeline.valueOf(0, property)

	var opt = this.defaultConstraint
	var editor = null
	var name = property.name
	if (name in this.constraints)
		opt = xtend(opt, this.constraints[name])

	//custom editor
	if (name in this.editors &&
			typeof this.editors[name] === 'function') {
		return this.editors[name](timeline, property, value, opt)
	}

	if (typeof value === 'number') {
		editor = NumberEditors(1, opt)
	} else if (Array.isArray(value)) {
		editor = NumberEditors(value.length, opt)
	}
	if (editor)
		editor.value = value
	if (typeof editor.on === 'function') {
		editor.on('edit-start', this._setValueEditor.bind(this, editor))
		editor.on('edit-stop', this._clearValueEditor.bind(this))
	}
	return editor
}

Editor.prototype._setValueEditor = function(editor) {
	this.currentEditor = editor
}

Editor.prototype._clearValueEditor = function() {
	this.currentEditor = null
}

function setVisible(timelineData, vis) {
	if (vis) {
		classes.remove(timelineData.animationContainer, 'hide')
		classes.remove(timelineData.element, 'hide')
	} else {
		classes.add(timelineData.animationContainer, 'hide')
		classes.add(timelineData.element, 'hide')
	}

}

Editor.prototype.hideAll = function() {
	this.timelinesData.forEach(function(t) {
		setVisible(t, false)
	})
}

Editor.prototype.showAll = function() {
	this.timelinesData.forEach(function(t) {
		setVisible(t, true)
	})
}

Editor.prototype.hide = function(name) {
	var ret = this.timelineData(name)
	if (ret)
		setVisible(ret, false)
}

Editor.prototype.show = function(name) {
	var ret = this.timelineData(name)
	if (ret)
		setVisible(ret, true)
}

Editor.prototype._toggleKeyframe = function(timelineData, propertyData) {
	var time = this.playhead()
	propertyData.toggleKeyframe(this, timelineData.timeline, time)
	this._updateProperties()
}

Editor.prototype._removeKeyframeAt = function(timelineData, propertyData, frame) {
	var idx = propertyData.property.keyframes.frames.indexOf(frame)
	if (idx !== -1) {
		propertyData.removeKeyframeAt(this, timelineData.timeline, idx)
		this._updateProperties()
	}
}

Editor.prototype._removeKeyframe = function(timelineData, propertyData) {
	var time = this.playhead()
	propertyData.removeKeyframe(this, timelineData.timeline, time)
	this._updateProperties()
}

Editor.prototype._createKeyframe = function(propertyData, keyframe) {
	//TODO: use keyframe-data here
	var ret = {
		element: domify('
'),
		keyframe: keyframe,
		propertyData: propertyData
	}

	ret.element.style.left = Math.round(keyframe.time*SCALE)+'px'
	events.on(ret.element, 'mousedown', function(ev) {
		this.draggingKeyframe = ret
	}.bind(this))
	events.on(ret.element, 'dblclick', function(ev) {
		ev.stopPropagation()
    	ev.preventDefault()

		if (ev.shiftKey) {
			this.draggingKeyframe = null
			this._removeKeyframeAt(propertyData.timelineData, propertyData, keyframe)
		}
	}.bind(this))
	return ret
}

Editor.prototype.appendTo = function(element) {
	element.appendChild(this.element)
}

Editor.prototype.timelines = function() {
	return this.timelinesData.map(function(t) {
		return { name: t.name, timeline: t.timeline.export() }
	})
}

Editor.prototype.constraint = function(name, constraints) {
	if (Array.isArray(name)) {
		name.forEach(function(n) {
			this.constraints[n] = constraints
		}.bind(this))
	}
	else
		this.constraints[name] = constraints
}

Editor.prototype.clear = function() {
	this.timelinesData.forEach(function(t) {
		t.dispose()
	})
	this.timelinesData.length = 0
}

Editor.prototype.shy = function(names) {
	names = typeof names === 'string' ? [names] : names
	names.forEach(function(n) {
		if (this.shyNames.indexOf(n) === -1)
			this.shyNames.push(n)
	}.bind(this))
	this._updateShyLayers()
	return this
}

Editor.prototype._updateShyLayers = function() {
	var shyNames = this.shyNames
	this.timelinesData.forEach(function(t) {
		t.propertyData.forEach(function(p) {
			var shy = shyNames.indexOf(p.property.name) !== -1
			classes.remove(p.element, 'shy')
			classes.remove(p.animationElement, 'shy')
			if (shy) {
				classes.add(p.element, 'shy')
				classes.add(p.animationElement, 'shy')
			}
		})
	})
}

Editor.prototype.add = function(timeline, name) {
	var ret = Base.prototype.add.call(this, timeline, name)
	var dur = timeline.duration()
	ret.animationContainer.style.minWidth = Math.round((dur+1.0)*SCALE)+'px'
	return ret
}

module.exports = Editor<commit_msg>fixing bug with value editor<commit_after>var Base = require('./base')
var inherits = require('inherits')
var classes = require('dom-classes')
var domify = require('domify')
var clickdrag = require('clickdrag')
var events = require('dom-events')
var keycode = require('keycode')
var getMouseOffset = require('mouse-event-offset')
var xtend = require('xtend')

var NumberEditors = require('./dom/number-editors')
var createTimeline = require('./dom/create-timeline')
var SelectBox = require('./dom/select-box')
var eases = require('eases')

var noop = function() { return null }

var SCALE = 100

function Editor() {
	if (!(this instanceof Editor))
		return new Editor()

	Base.call(this)

	this.defaultConstraint = { decimals: 1 }
	this.easings = Object.keys(eases)
	this.easings = this.easings.filter(function(e) {
		return 'linear'
	})
	this.easings.unshift({ disabled: true, name: '—' })
	this.easings.unshift('linear')

	this.constraints = {}
	this.editors = {}
	this.shyNames = []
	this.keyEvents = true
	// this.editable = true

    this.element = domify('
')
    this.leftPanel = domify('
')
    this.rightPanel = domify('
')
    this.element.appendChild(this.leftPanel)
    this.element.appendChild(this.rightPanel)

    this.playheadElement = domify('
')
    this.rightPanel.appendChild(this.playheadElement)

    this.on('playhead', handlePlayhead.bind(this))
    this.on('keyframe-toggle', this._toggleKeyframe.bind(this))
    this.on('keyframe-next', keyframeNext.bind(this, true))
    this.on('keyframe-previous', keyframeNext.bind(this, false))
    this.on('keyframe-remove', this._removeKeyframe.bind(this))

    this.on('load', handlePlayhead.bind(this))
    this.on('load', this._updateShyLayers.bind(this))

    events.on(document, 'keydown', handleKey.bind(this), false)
    this.currentEditor = null

    this.draggable = clickdrag(this.rightPanel)
    this.propertyDrag = null
    this.draggable.on('start', this._onDragStart.bind(this))
    this.draggable.on('move', this._onDrag.bind(this))
    this.draggable.on('end', onDragEnd.bind(this))
    this.draggingKeyframe = null

    this.highlightProperty = null
    this.on('highlight-property', function(prop) {
    	if (this.highlightProperty && prop !== this.highlightProperty) {
    		var old = this.highlightProperty
    		classes.remove(old.element, 'highlight')
    		classes.remove(old.animationElement, 'highlight')
    	}
    	this.highlightProperty = prop
    	classes.add(prop.element, 'highlight')
    	classes.add(prop.animationElement, 'highlight')
    }.bind(this))

    this.on('select-easing', function(propertyData) {
    	var ease = propertyData.easingBox.selected()
    	if (propertyData.currentKeyframe) {
    		propertyData.currentKeyframe.ease = ease
    	} else {
    		var keyframes = propertyData.property.keyframes
    		var next = keyframes.next( this.playhead() )
    		if (next)
    			next.ease = ease
    	}
    }.bind(this))

}

inherits(Editor, Base)

function handleKey(ev) {
	if (!this.keyEvents)
		return

	var key = keycode(ev)
	if (key === 'left') {
		if (this.currentEditor && this.currentEditor.editing)
			return

		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-previous', this.highlightProperty)
	} else if (key === 'right') {
		if (this.currentEditor && this.currentEditor.editing)
			return

		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-next', this.highlightProperty)
	} else if (key === 'k') {
		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-toggle', this.highlightProperty.timelineData, this.highlightProperty)
	} else if (key === 'delete' || key === 'backspace') {
		if (this.currentEditor && this.currentEditor.editing)
			return

		ev.preventDefault()
		if (this.highlightProperty)
			this.emit('keyframe-remove', this.highlightProperty.timelineData, this.highlightProperty)
	}
}

function keyframeNext(goNext, propertyData) {
	var keyframes = propertyData.property.keyframes
	var time = this.playhead()
    var next = goNext ? keyframes.next(time) : keyframes.previous(time)
    if (next) {
        this.playhead(next.time)
    }
}

Editor.prototype._onDragStart = function(ev, offset, delta) {
	if (this.draggingKeyframe)
		this.propertyDrag = this.draggingKeyframe.element.parentNode
	else
		this.propertyDrag = ev.target
	this._onDrag(ev, offset, delta)
}

Editor.prototype._onDrag = function(ev, offset, delta) {
	ev.preventDefault()

	if (!this.propertyDrag)
		return

	var rect = this.propertyDrag.getBoundingClientRect()
    offset = getMouseOffset(ev, { clientRect: rect })
    offset.x = Math.max(0, offset.x)

	if (this.draggingKeyframe) {
		this.draggingKeyframe.element.style.left = Math.round(offset.x)+'px'
		this.draggingKeyframe.keyframe.time = offset.x/SCALE
		this.draggingKeyframe.propertyData.updateKeyframes()
		this._updateProperties()
	} else {
		this.playhead(offset.x / SCALE)
	}
}

function onDragEnd(ev, offset, delta) {
	this.draggingKeyframe = null
	this.propertyDrag = null
}

function handlePlayhead(time) {
	this.playheadElement.style.left = Math.round(time*SCALE)+'px'
	this._updateProperties()
}

//Creates a new timeline object which has { element, open, name, dispose }
Editor.prototype._createTimeline = function(timeline, name) {
	return createTimeline(this, timeline, name)
}

Editor.prototype._updateProperties = function() {
    var curTime = this.playhead()
    this.timelinesData.forEach(function(tData) {
    	var timeline = tData.timeline

        tData.propertyData.forEach(function(propData) {
        	var prop = propData.property
			var curVal = timeline.valueOf(curTime, prop)
			propData.updateEditor(curVal)

            var highlightIdx = prop.keyframes.getIndex(curTime)
            var highlight = prop.keyframes.frames[highlightIdx]

            propData.keyframeData.forEach(function(k) {
            	classes.remove(k.element, 'highlight')
            	if (k.keyframe===highlight) {
	                classes.add(k.element, 'highlight')
	            }
            })

            var nextFrame = highlight || prop.keyframes.next(curTime)
            var curEase = nextFrame
            var hasEasing = nextFrame && nextFrame !== prop.keyframes.frames[0]

            classes.remove(propData.element, 'has-easing')
            if (hasEasing)
            	classes.add(propData.element, 'has-easing')

            if (propData.easingBox) {
            	var box = propData.easingBox.element
            	if (hasEasing) {
	            	box.removeAttribute('disabled')
	            	propData.easingBox.select(curEase.ease || 'linear')
	            } else
	            	box.setAttribute('disabled', 'disabled')
	        }
            propData.currentKeyframe = highlight
        })
    })
	this.emit('update')
}

Editor.prototype.createEasingSelect = function(options) {
	return new SelectBox(xtend(options||{}, { data: this.easings }))
}

Editor.prototype.valueEditor = function(name, func) {
	if (!func)
		this.editors[name] = undefined
	else
		this.editors[name] = func
	return this
}

Editor.prototype.createValueEditor = function(timeline, property) {
	var value = timeline.valueOf(0, property)

	var opt = this.defaultConstraint
	var editor = null
	var name = property.name
	if (name in this.constraints)
		opt = xtend(opt, this.constraints[name])

	//custom editor
	if (name in this.editors &&
			typeof this.editors[name] === 'function') {
		return this.editors[name](timeline, property, value, opt)
	}

	if (typeof value === 'number') {
		editor = NumberEditors(1, opt)
	} else if (Array.isArray(value)) {
		editor = NumberEditors(value.length, opt)
	}
	if (editor) {
		editor.value = value
		if (typeof editor.on === 'function') {
			editor.on('edit-start', this._setValueEditor.bind(this, editor))
			editor.on('edit-stop', this._clearValueEditor.bind(this))
		}
	}
	return editor
}

Editor.prototype._setValueEditor = function(editor) {
	this.currentEditor = editor
}

Editor.prototype._clearValueEditor = function() {
	this.currentEditor = null
}

function setVisible(timelineData, vis) {
	if (vis) {
		classes.remove(timelineData.animationContainer, 'hide')
		classes.remove(timelineData.element, 'hide')
	} else {
		classes.add(timelineData.animationContainer, 'hide')
		classes.add(timelineData.element, 'hide')
	}

}

Editor.prototype.hideAll = function() {
	this.timelinesData.forEach(function(t) {
		setVisible(t, false)
	})
}

Editor.prototype.showAll = function() {
	this.timelinesData.forEach(function(t) {
		setVisible(t, true)
	})
}

Editor.prototype.hide = function(name) {
	var ret = this.timelineData(name)
	if (ret)
		setVisible(ret, false)
}

Editor.prototype.show = function(name) {
	var ret = this.timelineData(name)
	if (ret)
		setVisible(ret, true)
}

Editor.prototype._toggleKeyframe = function(timelineData, propertyData) {
	var time = this.playhead()
	propertyData.toggleKeyframe(this, timelineData.timeline, time)
	this._updateProperties()
}

Editor.prototype._removeKeyframeAt = function(timelineData, propertyData, frame) {
	var idx = propertyData.property.keyframes.frames.indexOf(frame)
	if (idx !== -1) {
		propertyData.removeKeyframeAt(this, timelineData.timeline, idx)
		this._updateProperties()
	}
}

Editor.prototype._removeKeyframe = function(timelineData, propertyData) {
	var time = this.playhead()
	propertyData.removeKeyframe(this, timelineData.timeline, time)
	this._updateProperties()
}

Editor.prototype._createKeyframe = function(propertyData, keyframe) {
	//TODO: use keyframe-data here
	var ret = {
		element: domify('
'),
		keyframe: keyframe,
		propertyData: propertyData
	}

	ret.element.style.left = Math.round(keyframe.time*SCALE)+'px'
	events.on(ret.element, 'mousedown', function(ev) {
		this.draggingKeyframe = ret
	}.bind(this))
	events.on(ret.element, 'dblclick', function(ev) {
		ev.stopPropagation()
    	ev.preventDefault()

		if (ev.shiftKey) {
			this.draggingKeyframe = null
			this._removeKeyframeAt(propertyData.timelineData, propertyData, keyframe)
		}
	}.bind(this))
	return ret
}

Editor.prototype.appendTo = function(element) {
	element.appendChild(this.element)
}

Editor.prototype.timelines = function() {
	return this.timelinesData.map(function(t) {
		return { name: t.name, timeline: t.timeline.export() }
	})
}

Editor.prototype.constraint = function(name, constraints) {
	if (Array.isArray(name)) {
		name.forEach(function(n) {
			this.constraints[n] = constraints
		}.bind(this))
	}
	else
		this.constraints[name] = constraints
}

Editor.prototype.clear = function() {
	this.timelinesData.forEach(function(t) {
		t.dispose()
	})
	this.timelinesData.length = 0
}

Editor.prototype.shy = function(names) {
	names = typeof names === 'string' ? [names] : names
	names.forEach(function(n) {
		if (this.shyNames.indexOf(n) === -1)
			this.shyNames.push(n)
	}.bind(this))
	this._updateShyLayers()
	return this
}

Editor.prototype._updateShyLayers = function() {
	var shyNames = this.shyNames
	this.timelinesData.forEach(function(t) {
		t.propertyData.forEach(function(p) {
			var shy = shyNames.indexOf(p.property.name) !== -1
			classes.remove(p.element, 'shy')
			classes.remove(p.animationElement, 'shy')
			if (shy) {
				classes.add(p.element, 'shy')
				classes.add(p.animationElement, 'shy')
			}
		})
	})
}

Editor.prototype.add = function(timeline, name) {
	var ret = Base.prototype.add.call(this, timeline, name)
	var dur = timeline.duration()
	ret.animationContainer.style.minWidth = Math.round((dur+1.0)*SCALE)+'px'
	return ret
}

module.exports = Editor<|endoftext|>


<commit_before>'use strict';

// MODULES //

var tape = require( 'tape' );
var noop = require( '@stdlib/utils/noop' );
var omitBy = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof omitBy, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if provided a source object argument which is not an object', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		undefined,
		true
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			omitBy( value, noop );
		};
	}
});

tape( 'the function throws an error if provided a second argument which is not a function', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		undefined,
		true,
		{},
		[]
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			omitBy( {}, value );
		};
	}
});

tape( 'the function returns a partial copy of an object', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key, value ) {
		return ( value > 1 && value !== 4 );
	}

	obj1 = {
		'a': 1,
		'b': 2,
		'c': 3,
		'd': 4,
		'e': 5
	};

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': 1,
		'd': 4
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function returns a partial copy of an object', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key ) {
		return ( key === 'b' );
	}

	obj1 = {
		'a': 1,
		'b': 2,
		'c': 3,
		'd': 4,
		'e': 5
	};

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': 1,
		'c': 3,
		'd': 4,
		'e': 5
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function ignores inherited properties', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key, value ) {
		if ( key === 'f' || key === 'g' ) {
			t.ok( false, 'returns an inherited property' );
		}
		return ( value > 1 && value !== 4 );
	}

	function Foo() {
		this.a = 1;
		this.b = 2;
		this.c = 3;
		this.d = 4;
		this.e = 5;
		return this;
	}

	Foo.prototype.f = 6;
	Foo.prototype.g = 7;

	obj1 = new Foo();

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': 1,
		'd': 4
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function returns accepts non-plain objects', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key ) {
		return ( parseInt( key, 10 ) % 2 === 0 );
	}

	obj1 = [ 0, 1, 2, 3, 4, 5 ];

	obj2 = omitBy( obj1, predicate );

	expected = {
		'1': 1,
		'3': 3,
		'5': 5
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function returns a shallow copy', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key ) {
		return ( key === 'b' || key === 'c' || key === 'e' );
	}

	obj1 = {
		'a': [ 1 ],
		'b': [ 2 ],
		'c': [ 3 ],
		'd': [ 4 ],
		'e': [ 5 ]
	};

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': obj1.a,
		'd': obj1.d
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.strictEqual( obj2.a, obj1.a, 'returns shallow copy' );
	t.strictEqual( obj2.d, obj1.d, 'returns shallow copy' );

	t.end();
});
<commit_msg>Fix test description<commit_after>'use strict';

// MODULES //

var tape = require( 'tape' );
var noop = require( '@stdlib/utils/noop' );
var omitBy = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof omitBy, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if provided a source object argument which is not an object', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		undefined,
		true
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			omitBy( value, noop );
		};
	}
});

tape( 'the function throws an error if provided a second argument which is not a function', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		undefined,
		true,
		{},
		[]
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			omitBy( {}, value );
		};
	}
});

tape( 'the function returns a partial copy of an object', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key, value ) {
		return ( value > 1 && value !== 4 );
	}

	obj1 = {
		'a': 1,
		'b': 2,
		'c': 3,
		'd': 4,
		'e': 5
	};

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': 1,
		'd': 4
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function returns a partial copy of an object', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key ) {
		return ( key === 'b' );
	}

	obj1 = {
		'a': 1,
		'b': 2,
		'c': 3,
		'd': 4,
		'e': 5
	};

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': 1,
		'c': 3,
		'd': 4,
		'e': 5
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function ignores inherited properties', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key, value ) {
		if ( key === 'f' || key === 'g' ) {
			t.ok( false, 'returns an inherited property' );
		}
		return ( value > 1 && value !== 4 );
	}

	function Foo() {
		this.a = 1;
		this.b = 2;
		this.c = 3;
		this.d = 4;
		this.e = 5;
		return this;
	}

	Foo.prototype.f = 6;
	Foo.prototype.g = 7;

	obj1 = new Foo();

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': 1,
		'd': 4
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function accepts non-plain objects', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key ) {
		return ( parseInt( key, 10 ) % 2 === 0 );
	}

	obj1 = [ 0, 1, 2, 3, 4, 5 ];

	obj2 = omitBy( obj1, predicate );

	expected = {
		'1': 1,
		'3': 3,
		'5': 5
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.end();
});

tape( 'the function returns a shallow copy', function test( t ) {
	var expected;
	var obj1;
	var obj2;

	function predicate( key ) {
		return ( key === 'b' || key === 'c' || key === 'e' );
	}

	obj1 = {
		'a': [ 1 ],
		'b': [ 2 ],
		'c': [ 3 ],
		'd': [ 4 ],
		'e': [ 5 ]
	};

	obj2 = omitBy( obj1, predicate );

	expected = {
		'a': obj1.a,
		'd': obj1.d
	};

	t.deepEqual( obj2, expected, 'returns expected object' );
	t.strictEqual( obj2.a, obj1.a, 'returns shallow copy' );
	t.strictEqual( obj2.d, obj1.d, 'returns shallow copy' );

	t.end();
});
<|endoftext|>


<commit_before>/*
 * servers.js: Instance methods for working with servers from DigitalOcean
 *
 * (C) 2012 Nodejitsu Inc.
 *
 */
var request  = require('request'),
    base     = require('../../../core/compute'),
    pkgcloud = require('../../../../../lib/pkgcloud'),
    errs     = require('errs'),
    compute  = pkgcloud.providers.digitalocean.compute;

//
// ### function getVersion (callback)
// #### @callback {function} f(err, version).
//
// Gets the current API version
//
exports.getVersion = function getVersion(callback) {
  return errs.handle(
    errs.create({ message: "DigitalOcean's API does not support versioning" }),
    callback
  );
};

//
// ### function getLimits (callback)
// #### @callback {function} f(err, version).
//
// Gets the current API limits
//
exports.getLimits = function getLimits(callback) {
  return errs.handle(
    errs.create({ message: "DigitalOcean's API is not rate limited" }),
    callback
  );
};

//
// ### function getServers (callback)
// #### @options {Object} Options when getting servers
// ####   @options.offset {number} Number of servers to skip when listing
// ####   @options.limit  {number} Number of servers to return
// #### @callback {function} f(err, servers). `servers` is an array that
// represents the servers that are available to your account
//
// Lists all servers available to your account.
//
exports.getServers = function getServers(options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }

  var self = this;
  return this.request(
    {
      path: '/droplets',
      qs: options
    },
    function (err, body, res) {
      if (err) {
        return callback(err);
      }

      callback(null, body.droplets.map(function (result) {
        return new compute.Server(self, result);
      }), res);
    }
  );
};

//
// ### function createServer (options, callback)
// #### @opts {Object} **Optional** options
// ####    @name     {String} **Optional** a name for your server
// ####    @flavor   {String|Flavor} **Optional** flavor to use for this image
// ####    @image    {String|Image} **Optional** the image to use
// ####    @required {Boolean} **Optional** Validate if flavor, name,
// and image are present
// ####    @*        {*} **Optional** Anything platform specific
// #### @callback {Function} f(err, server).
//
// Creates a server with the specified options. The flavor
// properties of the options can be instances of Flavor
// OR ids to those entities in DigitalOcean.
//
exports.createServer = function createServer(options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options  = {};
  }

  options = options || {}; // no args

  var self = this,
      createOptions = {
        path: '/droplets/new',
        qs: {}
      };

  ['flavor', 'image', 'name'].forEach(function (member) {
    if (!options[member]) {
      return errs.handle(
        errs.create({ message: 'options.' + member + ' is a required argument.' }),
        callback
      );
    }
  });

  createOptions.qs.name      = options.name;
  createOptions.qs.region_id = options.region || options.region_id || 1;
  createOptions.qs.size_id   = options.flavor instanceof base.Flavor
    ? options.flavor.id
    : options.flavor;

  createOptions.qs.image_id = options.image instanceof base.Image
    ? options.image.id
    : options.image;

  //
  // Integrate with existing keys API, but support keyNames as well
  // which can be a single string or an Array.
  //
  if (options.keyname) {
    createOptions.qs.ssh_key_ids = options.keyname;
  }
  else if (options.keynames) {
    createOptions.qs.ssh_key_ids = Array.isArray(options.keynames)
      ? options.keynames.join(',')
      : options.keynames;
  }

  return this.request(createOptions, function (err, body, res) {
    return err
      ? callback(err)
      : callback(null, new compute.Server(self, body.droplet), res);
  });
};

//
// ### function destroyServer(server, callback)
// #### @server {Server|String} Server id or a server
// #### [@options] {object} Pass optional optinos for deletion
// #### [options.scrubData] Optionally disable scrubbing data (boolean),
//        default is to scrub data from Digital Ocean servers
//
// #### @callback {Function} f(err, serverId).
//
// Destroy a server in DigitalOcean.
//
exports.destroyServer = function destroyServer(server, options, callback) {
  var serverId = server instanceof base.Server ? server.id : server,
      self = this;

  if (typeof options === 'function') {
    callback = options;
    options = {};
  }

  this.request({
    path: '/droplets/' + serverId + '/destroy',
    qs: {
      scrub_data: (typeof options.scrubData === 'boolean')
        ? (options.scrubData ? '1' : '0')
        : '1'
    }
  }, function (err, body, res) {
    return err ? callback(err) : callback(null, { ok: serverId }, res);
  });
};

//
// ### function getServer(server, callback)
// #### @server {Server|String} Server id or a server
// #### @callback {Function} f(err, serverId).
//
// Gets a server in DigitalOcean.
//
exports.getServer = function getServer(server, callback) {
  var serverId = server instanceof base.Server ? server.id : server,
      self     = this;

  return this.request({
    path: '/droplets/' + serverId
  }, function (err, body, res) {
    return !err
      ? callback(null, new compute.Server(self, body.droplet), res)
      : callback(err);
  });
};

//
// ### function rebootServer (server, options, callback)
// #### @server   {Server|String} The server to reboot
// #### @callback {Function} f(err, server).
//
// Reboots a server
//
exports.rebootServer = function rebootServer(server, callback) {
  var serverId = server instanceof base.Server ? server.id : server;
  return this.request({
    path: '/droplets/' + serverId + '/reboot'
  }, function (err, body, res) {
    return err
      ? callback(err)
      : callback(null, { ok: serverId }, res);
  });
};

//
// ### function renameServer(server, name, callback)
// #### @server {Server|String} Server id or a server
// #### @name   {String} New name to apply to the server
// #### @callback {Function} f(err, server).
//
// Renames a server
//
exports.renameServer = function renameServer(server, name, callback) {
  var serverId = server instanceof base.Server ? server.id : server;
  return this.request({
    path: '/droplets/' + serverId + '/rename',
    qs: { name: name }
  }, function (err, body, res) {
    return err
      ? callback(err)
      : callback(null, { ok: serverId }, res);
  });
};
<commit_msg>Minor type and comment cleanup<commit_after>/*
 * servers.js: Instance methods for working with servers from DigitalOcean
 *
 * (C) 2012 Nodejitsu Inc.
 *
 */
var request  = require('request'),
    base     = require('../../../core/compute'),
    pkgcloud = require('../../../../../lib/pkgcloud'),
    errs     = require('errs'),
    compute  = pkgcloud.providers.digitalocean.compute;

//
// ### function getVersion (callback)
// #### @callback {function} f(err, version).
//
// Gets the current API version
//
exports.getVersion = function getVersion(callback) {
  return errs.handle(
    errs.create({ message: "DigitalOcean's API does not support versioning" }),
    callback
  );
};

//
// ### function getLimits (callback)
// #### @callback {function} f(err, version).
//
// Gets the current API limits
//
exports.getLimits = function getLimits(callback) {
  return errs.handle(
    errs.create({ message: "DigitalOcean's API is not rate limited" }),
    callback
  );
};

//
// ### function getServers (callback)
// #### @options {Object} Options when getting servers
// ####   @options.offset {number} Number of servers to skip when listing
// ####   @options.limit  {number} Number of servers to return
// #### @callback {function} f(err, servers). `servers` is an array that
// represents the servers that are available to your account
//
// Lists all servers available to your account.
//
exports.getServers = function getServers(options, callback) {
  if (!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }

  var self = this;
  return this.request(
    {
      path: '/droplets',
      qs: options
    },
    function (err, body, res) {
      if (err) {
        return callback(err);
      }

      callback(null, body.droplets.map(function (result) {
        return new compute.Server(self, result);
      }), res);
    }
  );
};

//
// ### function createServer (options, callback)
// #### @opts {Object} **Optional** options
// ####    @name     {String} **Optional** a name for your server
// ####    @flavor   {String|Flavor} **Optional** flavor to use for this image
// ####    @image    {String|Image} **Optional** the image to use
// ####    @required {Boolean} **Optional** Validate if flavor, name,
// and image are present
// ####    @*        {*} **Optional** Anything platform specific
// #### @callback {Function} f(err, server).
//
// Creates a server with the specified options. The flavor
// properties of the options can be instances of Flavor
// OR ids to those entities in DigitalOcean.
//
exports.createServer = function createServer(options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options  = {};
  }

  options = options || {}; // no args

  var self = this,
      createOptions = {
        path: '/droplets/new',
        qs: {}
      };

  ['flavor', 'image', 'name'].forEach(function (member) {
    if (!options[member]) {
      return errs.handle(
        errs.create({ message: 'options.' + member + ' is a required argument.' }),
        callback
      );
    }
  });

  createOptions.qs.name      = options.name;
  createOptions.qs.region_id = options.region || options.region_id || 1;
  createOptions.qs.size_id   = options.flavor instanceof base.Flavor
    ? options.flavor.id
    : options.flavor;

  createOptions.qs.image_id = options.image instanceof base.Image
    ? options.image.id
    : options.image;

  //
  // Integrate with existing keys API, but support keyNames as well
  // which can be a single string or an Array.
  //
  if (options.keyname) {
    createOptions.qs.ssh_key_ids = options.keyname;
  }
  else if (options.keynames) {
    createOptions.qs.ssh_key_ids = Array.isArray(options.keynames)
      ? options.keynames.join(',')
      : options.keynames;
  }

  return this.request(createOptions, function (err, body, res) {
    return err
      ? callback(err)
      : callback(null, new compute.Server(self, body.droplet), res);
  });
};

//
// ### function destroyServer(server, callback)
// #### @server {Server|String} Server id or a server
// #### [@options] {object} Pass optioos for deletion
// #### [options.scrubData] Optionally disable scrubbing data (boolean),
//        default (true) is to scrub data from Digital Ocean servers
//
// #### @callback {Function} f(err, serverId).
//
// Destroy a server in DigitalOcean.
//
exports.destroyServer = function destroyServer(server, options, callback) {
  var serverId = server instanceof base.Server ? server.id : server,
      self = this;

  if (typeof options === 'function') {
    callback = options;
    options = {};
  }

  this.request({
    path: '/droplets/' + serverId + '/destroy',
    qs: {
      scrub_data: (typeof options.scrubData === 'boolean')
        ? (options.scrubData ? '1' : '0')
        : '1'
    }
  }, function (err, body, res) {
    return err ? callback(err) : callback(null, { ok: serverId }, res);
  });
};

//
// ### function getServer(server, callback)
// #### @server {Server|String} Server id or a server
// #### @callback {Function} f(err, serverId).
//
// Gets a server in DigitalOcean.
//
exports.getServer = function getServer(server, callback) {
  var serverId = server instanceof base.Server ? server.id : server,
      self     = this;

  return this.request({
    path: '/droplets/' + serverId
  }, function (err, body, res) {
    return !err
      ? callback(null, new compute.Server(self, body.droplet), res)
      : callback(err);
  });
};

//
// ### function rebootServer (server, options, callback)
// #### @server   {Server|String} The server to reboot
// #### @callback {Function} f(err, server).
//
// Reboots a server
//
exports.rebootServer = function rebootServer(server, callback) {
  var serverId = server instanceof base.Server ? server.id : server;
  return this.request({
    path: '/droplets/' + serverId + '/reboot'
  }, function (err, body, res) {
    return err
      ? callback(err)
      : callback(null, { ok: serverId }, res);
  });
};

//
// ### function renameServer(server, name, callback)
// #### @server {Server|String} Server id or a server
// #### @name   {String} New name to apply to the server
// #### @callback {Function} f(err, server).
//
// Renames a server
//
exports.renameServer = function renameServer(server, name, callback) {
  var serverId = server instanceof base.Server ? server.id : server;
  return this.request({
    path: '/droplets/' + serverId + '/rename',
    qs: { name: name }
  }, function (err, body, res) {
    return err
      ? callback(err)
      : callback(null, { ok: serverId }, res);
  });
};
<|endoftext|>


<commit_before>var fs = require( "fs" );
var path = require( "path" );

/*
 * The expressions object contains the regular expressions that each line is checked against. If a expression
 * needs a value it is specified inside the first pair of round brackets ().
 */
expressions = {
    DEFINE: /^\s*\/\/\s+#define\s+(\S+)/,
    INCLUDE: /^\s*\/\/\s+#include\s+"([^"]+)"/,
    IFDEF: /^\s*\/\/\s+#ifdef\s+(\S+)/,
    IFNDEF: /^\s*\/\/\s+#ifndef\s+(\S+)/,
    ENDIF: /^\s*\/\/\s+#endif/,
    UNDEFINE: /^\s*\/\/\s+#undefine\s+(\S+)/,
    WARNING: /^\s*\/\/\s+#warning\s+"([^"]+)"/,
    ERROR: /^\s*\/\/\s+#error\s+"([^"]+)"/
};

/*
 * The DEBUG flag can be setted to true from the outside to make uprocess print debug messages to stdout via console.log
 */
exports.DEBUG = false;

/*
 * the outputLineDelimiter is the string which is used to join all the lines in the end.
 */
exports.outputLineDelimiter = "\n";

/*
 * processFile takes a filename and an defines object and returns the processed text of the file. The file is parsed
 * linewise splitting at \n and \r and at any combination of it. The defines object is copied and all the defines inside
 * will be used as setted via define inside of the preprocessor. Includes in this file are made relative to the file.
 */
exports.processFile = function ( file, extDefines ) {

    var defines = ( typeof extDefines === "object" ) ? copyObject( extDefines ) : {};

    var lines = splitIntoLines( fs.readFileSync( file, "utf-8" ) );

    debugMsg( "Start of File: " + file );
    var newLines = processLines( lines, defines, path.dirname( file ), path.basename( file ) );
    debugMsg( "End of File: " + file );

    return newLines.join( exports.outputLineDelimiter );
};

/*
 * processText takes a string, an defines object, an includeDir and returns the processed text. It works the same
 * way processFile works, but all includes inside the given text are made relative to the given includeDir. Inside
 * included files the includes are made relative to the file relative to includeDir.
 */
exports.processText = function ( text, extDefines, includeDir ) {

    var defines = ( typeof extDefines === "object" ) ? copyObject( extDefines ) : {};

    var lines = splitIntoLines( text );

    var newLines = processLines( lines, defines, includeDir, "" );

    return newLines.join( exports.outputLineDelimiter );
};

/*
 * processLines is the internal function which takes an array of lines, an object with defines and an includeDir to
 * include files relative to.
 * It checks each line for a preprocessor expression and if it finds one it is evaluated and removed afterwards. The
 * variable containing the lineNumber is adjusted accordingly.
 * If the variable excluded is bigger than 0 this means the lines which do not contain another ifdef/ifndef or an endif
 * are ignored and excluded. If excluded is bigger than 0 AND it reaches an ifdef/ifndef excluded is raised by 1 and
 * if it reaches an endif it is lowered by 1 till it reaches 0.
 * define/undefine:
 * adds/removes a variablename to the defines object, which is used by reference, that means the define will be
 * setted outside of the call, too.
 * include:
 * loads a file and calls processLines recursively on it. the resulting lines are inserted.
 * warning/error:
 * raises a warning/error with the given message if it is reached
 * ifdef/ifndef:
 * ifdef will check if the given define is setted and ifndef will check if it isn't. If it isn't true the following
 * lines till the corresponding endif are excluded from the result, any other preprocessor expressions are ignored.
 * The corresponding endif is the endif which has the same amount of ifdef/ifndef and endif expressions in between
 * the ifdef/ifndef and endif expression.
 */
function processLines( lines, defines, includeDir, fileName ) {

    debugMsg( "Defines:" );
    debugMsg( defines );

    var openexpressions = [];

    var excluded = 0; //how many levels of ifdef/ifndef are to be excluded

    var expvalue;

    var originalLineNumber = 0;

    try {

        for ( var lineNumber = 0; lineNumber < lines.length; lineNumber += 1 ) {

            originalLineNumber += 1;

            if ( !excluded ) {

                //DEFINE
                if ( lines[lineNumber].match( expressions.DEFINE ) ) {
                    expvalue = lines[lineNumber].match( expressions.DEFINE )[1];
                    defines[expvalue] = true;
                    lines = removeSingleLine( lines, lineNumber );

                    lineNumber -= 1;
                    continue;
                }

                //UNDEFINE
                if ( lines[lineNumber].match( expressions.UNDEFINE ) ) {
                    expvalue = lines[lineNumber].match( expressions.UNDEFINE )[1];
                    if ( expvalue in defines ) {
                        delete defines[expvalue];
                    }
                    lines = removeSingleLine( lines, lineNumber );

                    lineNumber -= 1;
                    continue;
                }

                //INCLUDE
                if ( lines[lineNumber].match( expressions.INCLUDE ) ) {
                    expvalue = lines[lineNumber].match( expressions.INCLUDE )[1];

                    var includeFile = path.join( includeDir, expvalue );

                    var newLines = splitIntoLines( fs.readFileSync( includeFile, "utf-8" ) );

                    debugMsg( "start of File: " + includeFile );
                    newLines = processLines( newLines, defines, path.dirname( includeFile ), path.basename( includeFile ) ); // recurse
                    debugMsg( "end of File: " + includeFile );

                    lines = removeSingleLine( lines, lineNumber );
                    lines = insertLines( lines, lineNumber, newLines );

                    lineNumber += newLines.length - 1;
                    continue;
                }

                //WARNING
                if ( lines[lineNumber].match( expressions.WARNING ) ) {
                    expvalue = lines[lineNumber].match( expressions.WARNING )[1];

                    console.warn( '#warning: ' + expvalue + errorLocation( originalLineNumber, includeDir, fileName ) );

                    lines = removeSingleLine( lines, lineNumber );
                    lineNumber -= 1;
                    continue;
                }

                //ERROR
                if ( lines[lineNumber].match( expressions.ERROR ) ) {
                    expvalue = lines[lineNumber].match( expressions.ERROR )[1];

                    throw new Error( '#error: ' + expvalue ); //errorLocation gets append in the catch block
                }

            }

            //IFDEF
            if ( lines[lineNumber].match( expressions.IFDEF ) ) {

                openexpressions.push( lineNumber );
                expvalue = lines[lineNumber].match( expressions.IFDEF )[1];
                if ( !( expvalue in defines ) || excluded ) {
                    excluded += 1;
                }

                lines = removeSingleLine( lines, lineNumber );
                lineNumber -= 1;
                continue;
            }

            //IFNDEF
            if ( lines[lineNumber].match( expressions.IFNDEF ) ) {

                openexpressions.push( lineNumber );
                expvalue = lines[lineNumber].match( expressions.IFNDEF )[1];
                if ( ( expvalue in defines ) || excluded ) {
                    excluded += 1;
                }

                lines = removeSingleLine( lines, lineNumber );
                lineNumber -= 1;
                continue;
            }

            //ENDIF
            if ( lines[lineNumber].match( expressions.ENDIF ) ) {

                var startline = openexpressions.pop();
                if ( startline !== undefined ) {
                    if ( excluded ) {
                        lines = removeLines( lines, startline, lineNumber + 1 );
                        lineNumber = startline - 1;
                        excluded -= 1;
                    } else {
                        lines = removeSingleLine( lines, lineNumber );
                        lineNumber -= 1;
                    }
                    continue;
                } else {
                    throw new Error( "Too many ENDIF expressions in text!" );
                }
            }

        }

        originalLineNumber = 0;

        if ( openexpressions.length !== 0 ) {
            throw new Error( openexpressions.length + " missing ENDIF expressions!" );
        }

    } catch ( e ) {
        e.message += errorLocation( originalLineNumber, includeDir, fileName ) + "\n";
        throw e;
    }

    return lines;
};

/*
 * copyObj returns a one level deep copy of an object
 */
function copyObject( obj ) {
    var newObj = {};
    for ( k in obj ) {
        newObj[k] = obj[k];
    }
    return newObj;
}

/*
 * debugMsg prints a debug message if the DEBUG flag is setted to true
 */
function debugMsg( debugmsg ) {
    if ( exports.DEBUG ) {
        console.log( debugmsg );
    }
}

/*
 * removeSingleLine removes the line at index and returns the array.
 */
function removeSingleLine( lines, index ) {
    lines.splice( index, 1 );
    return lines;
}

/*
 * removeLines removes the lines from index start up to but not including index end and returns the array.
 */
function removeLines( lines, start, end ) {
    lines.splice( start, end - start );
    return lines;
}

/*
 * insertLines returns an array with at pos inserted newLines.
 */
function insertLines( lines, index, newLines ) {
    return lines.slice( 0, index ).concat( newLines ).concat( lines.slice( index ) );
}

/*
 * splitIntoLines splits a text into lines
 */
function splitIntoLines( text ) {
    return text.split( /[\r\n]{1,2}/gm );
}

/*
 * errorLocation with opt_linenumber and opt_filename
 */
function errorLocation( opt_linenumber, includeDir, opt_filename ) {

    var msg = "";
    if ( opt_linenumber || opt_filename ) {
        msg = '\noccured while processing';

        if ( opt_filename ) {
             msg += ' "' + path.join( includeDir, opt_filename ) + '"';
        }

        if ( opt_linenumber ) {
            msg += ' line ' + opt_linenumber;
        }
    }

    return msg;
}<commit_msg>Added an unknowncommand expression to find misspelled commands<commit_after>var fs = require( "fs" );
var path = require( "path" );

/*
 * The expressions object contains the regular expressions that each line is checked against. If a expression
 * needs a value it is specified inside the first pair of round brackets ().
 */
expressions = {
    DEFINE: /^\s*\/\/\s+#define\s+(\S+)/,
    INCLUDE: /^\s*\/\/\s+#include\s+"([^"]+)"/,
    IFDEF: /^\s*\/\/\s+#ifdef\s+(\S+)/,
    IFNDEF: /^\s*\/\/\s+#ifndef\s+(\S+)/,
    ENDIF: /^\s*\/\/\s+#endif/,
    UNDEFINE: /^\s*\/\/\s+#undefine\s+(\S+)/,
    WARNING: /^\s*\/\/\s+#warning\s+"([^"]+)"/,
    ERROR: /^\s*\/\/\s+#error\s+"([^"]+)"/,
    UNKNOWNCOMMAND: /^\s*\/\/\s+#([^\s]*)/
};

/*
 * The DEBUG flag can be setted to true from the outside to make uprocess print debug messages to stdout via console.log
 */
exports.DEBUG = false;

/*
 * the outputLineDelimiter is the string which is used to join all the lines in the end.
 */
exports.outputLineDelimiter = "\n";

/*
 * processFile takes a filename and an defines object and returns the processed text of the file. The file is parsed
 * linewise splitting at \n and \r and at any combination of it. The defines object is copied and all the defines inside
 * will be used as setted via define inside of the preprocessor. Includes in this file are made relative to the file.
 */
exports.processFile = function ( file, extDefines ) {

    var defines = ( typeof extDefines === "object" ) ? copyObject( extDefines ) : {};

    var lines = splitIntoLines( fs.readFileSync( file, "utf-8" ) );

    debugMsg( "Start of File: " + file );
    var newLines = processLines( lines, defines, path.dirname( file ), path.basename( file ) );
    debugMsg( "End of File: " + file );

    return newLines.join( exports.outputLineDelimiter );
};

/*
 * processText takes a string, an defines object, an includeDir and returns the processed text. It works the same
 * way processFile works, but all includes inside the given text are made relative to the given includeDir. Inside
 * included files the includes are made relative to the file relative to includeDir.
 */
exports.processText = function ( text, extDefines, includeDir ) {

    var defines = ( typeof extDefines === "object" ) ? copyObject( extDefines ) : {};

    var lines = splitIntoLines( text );

    var newLines = processLines( lines, defines, includeDir, "" );

    return newLines.join( exports.outputLineDelimiter );
};

/*
 * processLines is the internal function which takes an array of lines, an object with defines and an includeDir to
 * include files relative to.
 * It checks each line for a preprocessor expression and if it finds one it is evaluated and removed afterwards. The
 * variable containing the lineNumber is adjusted accordingly.
 * If the variable excluded is bigger than 0 this means the lines which do not contain another ifdef/ifndef or an endif
 * are ignored and excluded. If excluded is bigger than 0 AND it reaches an ifdef/ifndef excluded is raised by 1 and
 * if it reaches an endif it is lowered by 1 till it reaches 0.
 * define/undefine:
 * adds/removes a variablename to the defines object, which is used by reference, that means the define will be
 * setted outside of the call, too.
 * include:
 * loads a file and calls processLines recursively on it. the resulting lines are inserted.
 * warning/error:
 * raises a warning/error with the given message if it is reached
 * ifdef/ifndef:
 * ifdef will check if the given define is setted and ifndef will check if it isn't. If it isn't true the following
 * lines till the corresponding endif are excluded from the result, any other preprocessor expressions are ignored.
 * The corresponding endif is the endif which has the same amount of ifdef/ifndef and endif expressions in between
 * the ifdef/ifndef and endif expression.
 */
function processLines( lines, defines, includeDir, fileName ) {

    debugMsg( "Defines:" );
    debugMsg( defines );

    var openexpressions = [];

    var excluded = 0; //how many levels of ifdef/ifndef are to be excluded

    var expvalue;

    var originalLineNumber = 0;

    try {

        for ( var lineNumber = 0; lineNumber < lines.length; lineNumber += 1 ) {

            originalLineNumber += 1;

            //DEFINE
            if ( lines[lineNumber].match( expressions.DEFINE ) ) {
                if ( !excluded ) {
                    expvalue = lines[lineNumber].match( expressions.DEFINE )[1];
                    defines[expvalue] = true;
                    lines = removeSingleLine( lines, lineNumber );

                    lineNumber -= 1;
                    continue;
                }
            }

            //UNDEFINE
            else if ( lines[lineNumber].match( expressions.UNDEFINE ) ) {
                if ( !excluded ) {
                    expvalue = lines[lineNumber].match( expressions.UNDEFINE )[1];
                    if ( expvalue in defines ) {
                        delete defines[expvalue];
                    }
                    lines = removeSingleLine( lines, lineNumber );

                    lineNumber -= 1;
                    continue;
                }
            }

            //INCLUDE
            else if ( lines[lineNumber].match( expressions.INCLUDE ) ) {
                if ( !excluded ) {
                    expvalue = lines[lineNumber].match( expressions.INCLUDE )[1];

                    var includeFile = path.join( includeDir, expvalue );

                    var newLines = splitIntoLines( fs.readFileSync( includeFile, "utf-8" ) );

                    debugMsg( "start of File: " + includeFile );
                    newLines = processLines( newLines, defines, path.dirname( includeFile ), path.basename( includeFile ) ); // recurse
                    debugMsg( "end of File: " + includeFile );

                    lines = removeSingleLine( lines, lineNumber );
                    lines = insertLines( lines, lineNumber, newLines );

                    lineNumber += newLines.length - 1;
                    continue;
                }
            }

            //WARNING
            else if ( lines[lineNumber].match( expressions.WARNING ) ) {
                if ( !excluded ) {
                    expvalue = lines[lineNumber].match( expressions.WARNING )[1];

                    console.warn( '#warning: ' + expvalue + errorLocation( originalLineNumber, includeDir, fileName ) );

                    lines = removeSingleLine( lines, lineNumber );
                    lineNumber -= 1;
                    continue;
                }
            }

            //ERROR
            else if ( lines[lineNumber].match( expressions.ERROR ) ) {
                if ( !excluded ) {
                    expvalue = lines[lineNumber].match( expressions.ERROR )[1];

                    throw new Error( '#error: ' + expvalue ); //errorLocation gets append in the catch block
                }
            }

            //IFDEF
            else if ( lines[lineNumber].match( expressions.IFDEF ) ) {

                openexpressions.push( lineNumber );
                expvalue = lines[lineNumber].match( expressions.IFDEF )[1];
                if ( !( expvalue in defines ) || excluded ) {
                    excluded += 1;
                }

                lines = removeSingleLine( lines, lineNumber );
                lineNumber -= 1;
                continue;
            }

            //IFNDEF
            else if ( lines[lineNumber].match( expressions.IFNDEF ) ) {

                openexpressions.push( lineNumber );
                expvalue = lines[lineNumber].match( expressions.IFNDEF )[1];
                if ( ( expvalue in defines ) || excluded ) {
                    excluded += 1;
                }

                lines = removeSingleLine( lines, lineNumber );
                lineNumber -= 1;
                continue;
            }

            //ENDIF
            else if ( lines[lineNumber].match( expressions.ENDIF ) ) {

                var startline = openexpressions.pop();
                if ( startline !== undefined ) {
                    if ( excluded ) {
                        lines = removeLines( lines, startline, lineNumber + 1 );
                        lineNumber = startline - 1;
                        excluded -= 1;
                    } else {
                        lines = removeSingleLine( lines, lineNumber );
                        lineNumber -= 1;
                    }
                    continue;
                } else {
                    throw new Error( "Too many ENDIF expressions in text!" );
                }
            }

            // UNKNOWNCOMMAND
            else if ( lines[lineNumber].match( expressions.UNKNOWNCOMMAND ) ) {
                expvalue = lines[lineNumber].match( expressions.UNKNOWNCOMMAND )[1];
                console.warn( 'Unknown command #' + expvalue + " found " + errorLocation( originalLineNumber, includeDir, fileName ) );
            }

        }

        originalLineNumber = 0;

        if ( openexpressions.length !== 0 ) {
            throw new Error( openexpressions.length + " missing ENDIF expressions!" );
        }

    } catch ( e ) {
        e.message += errorLocation( originalLineNumber, includeDir, fileName ) + "\n";
        throw e;
    }

    return lines;
};

/*
 * copyObj returns a one level deep copy of an object
 */
function copyObject( obj ) {
    var newObj = {};
    for ( k in obj ) {
        newObj[k] = obj[k];
    }
    return newObj;
}

/*
 * debugMsg prints a debug message if the DEBUG flag is setted to true
 */
function debugMsg( debugmsg ) {
    if ( exports.DEBUG ) {
        console.log( debugmsg );
    }
}

/*
 * removeSingleLine removes the line at index and returns the array.
 */
function removeSingleLine( lines, index ) {
    lines.splice( index, 1 );
    return lines;
}

/*
 * removeLines removes the lines from index start up to but not including index end and returns the array.
 */
function removeLines( lines, start, end ) {
    lines.splice( start, end - start );
    return lines;
}

/*
 * insertLines returns an array with at pos inserted newLines.
 */
function insertLines( lines, index, newLines ) {
    return lines.slice( 0, index ).concat( newLines ).concat( lines.slice( index ) );
}

/*
 * splitIntoLines splits a text into lines
 */
function splitIntoLines( text ) {
    return text.split( /[\r\n]{1,2}/gm );
}

/*
 * errorLocation with opt_linenumber and opt_filename
 */
function errorLocation( opt_linenumber, includeDir, opt_filename ) {

    var msg = "";
    if ( opt_linenumber || opt_filename ) {
        msg = '\noccured while processing';

        if ( opt_filename ) {
             msg += ' "' + path.join( includeDir, opt_filename ) + '"';
        }

        if ( opt_linenumber ) {
            msg += ' line ' + opt_linenumber;
        }
    }

    return msg;
}<|endoftext|>