<commit_before>'use strict';

let app = require('../../../../../../server');
let request = require('supertest');
let users = require('dumonda-me-server-test-util').user;
let requestHandler = require('dumonda-me-server-test-util').requestHandler;
let dbDsl = require('dumonda-me-server-test-util').dbDSL;

describe('Integration Tests Login', function () {

    beforeEach(async function () {
        await dbDsl.init(2);
        dbDsl.createRegion('international', {de: 'internationalDe', en: 'internationalEn'});
        dbDsl.createRegion('region-1', {parentRegionId: 'international', de: 'Region1De', en: 'Region1En'});
        dbDsl.createRegion('region-2', {parentRegionId: 'international', de: 'Region2De', en: 'Region2En'});
        dbDsl.createRegion('region-3', {parentRegionId: 'international', de: 'Region3De', en: 'Region3En'});

        dbDsl.createMainTopic({topicId: 'topic1', descriptionDe: 'topic1De', descriptionEn: 'topic1En'});
        dbDsl.createMainTopic({topicId: 'topic2', descriptionDe: 'topic2De', descriptionEn: 'topic2En'});
        dbDsl.createSubTopic({
            parentTopicId: 'topic2', topicId: 'topic21', descriptionDe: 'topic21De', descriptionEn: 'topic21En'
        });
        dbDsl.createSubTopic({
            parentTopicId: 'topic2', topicId: 'topic22', descriptionDe: 'topic22De', descriptionEn: 'topic22En'
        });

        dbDsl.interestedTopics('1', {topics: ['topic1', 'topic21']});
        dbDsl.interestedRegions('1', {regions: ['region-1', 'region-3']});
        dbDsl.setInfoState('1', {infoState: 1});
        dbDsl.setUserLanguages('1', {languages: ['en', 'de']});
        dbDsl.setInfoState('2', {infoState: 0});
        dbDsl.setUserLanguages('2', {languages: ['en']});
        await dbDsl.sendToDb();
    });

    it('Login - Return a 400 when invalid username', function (done) {
        request(app).post('/api/login').send(users.invalidUsername).expect(400).end(done);
    });
    it('Login - Return a 400 when invalid password', function (done) {
        request(app).post('/api/login').send(users.invalidPassword).expect(400).end(done);
    });

    it('Login - Return a 200', function (done) {
        request(app).post('/api/login').send(users.validUser).expect(200).end(done);
    });

    it('Login with capital letters- Return a 200', function (done) {
        request(app).post('/api/login').send(users.validUser3).expect(200).end(done);
    });

    it('Login and getting all optional user data', async function () {
        let res = await requestHandler.login(users.validUser);
        res.status.should.equal(200);
        res.body.lang.should.equals('de');
        res.body.languages.length.should.equals(2);
        res.body.languages.should.includes('de');
        res.body.languages.should.includes('en');
        res.body.topics.length.should.equals(2);
        res.body.topics.should.includes('topic1');
        res.body.topics.should.includes('topic21');
        res.body.regions.length.should.equals(2);
        res.body.regions.should.includes('region-1');
        res.body.regions.should.includes('region-3');
        res.body.infoState.should.equals(1);
    });

    it('Login and getting user data', async function () {
        let res = await requestHandler.login(users.validUser2);
        res.status.should.equal(200);
        res.body.lang.should.equals('de');
        res.body.languages.length.should.equals(1);
        res.body.languages.should.includes('en');
        res.body.infoState.should.equals(0);
    });

    it('Logout - Return a 200', function (done) {
        request(app).post('/api/logout').send({}).expect(200).end(done);
    });
});<commit_msg>Added check if topics and regions are empty.<commit_after>'use strict';

let app = require('../../../../../../server');
let request = require('supertest');
let users = require('dumonda-me-server-test-util').user;
let requestHandler = require('dumonda-me-server-test-util').requestHandler;
let dbDsl = require('dumonda-me-server-test-util').dbDSL;

describe('Integration Tests Login', function () {

    beforeEach(async function () {
        await dbDsl.init(2);
        dbDsl.createRegion('international', {de: 'internationalDe', en: 'internationalEn'});
        dbDsl.createRegion('region-1', {parentRegionId: 'international', de: 'Region1De', en: 'Region1En'});
        dbDsl.createRegion('region-2', {parentRegionId: 'international', de: 'Region2De', en: 'Region2En'});
        dbDsl.createRegion('region-3', {parentRegionId: 'international', de: 'Region3De', en: 'Region3En'});

        dbDsl.createMainTopic({topicId: 'topic1', descriptionDe: 'topic1De', descriptionEn: 'topic1En'});
        dbDsl.createMainTopic({topicId: 'topic2', descriptionDe: 'topic2De', descriptionEn: 'topic2En'});
        dbDsl.createSubTopic({
            parentTopicId: 'topic2', topicId: 'topic21', descriptionDe: 'topic21De', descriptionEn: 'topic21En'
        });
        dbDsl.createSubTopic({
            parentTopicId: 'topic2', topicId: 'topic22', descriptionDe: 'topic22De', descriptionEn: 'topic22En'
        });

        dbDsl.interestedTopics('1', {topics: ['topic1', 'topic21']});
        dbDsl.interestedRegions('1', {regions: ['region-1', 'region-3']});
        dbDsl.setInfoState('1', {infoState: 1});
        dbDsl.setUserLanguages('1', {languages: ['en', 'de']});
        dbDsl.setInfoState('2', {infoState: 0});
        dbDsl.setUserLanguages('2', {languages: ['en']});
        await dbDsl.sendToDb();
    });

    it('Login - Return a 400 when invalid username', function (done) {
        request(app).post('/api/login').send(users.invalidUsername).expect(400).end(done);
    });
    it('Login - Return a 400 when invalid password', function (done) {
        request(app).post('/api/login').send(users.invalidPassword).expect(400).end(done);
    });

    it('Login - Return a 200', function (done) {
        request(app).post('/api/login').send(users.validUser).expect(200).end(done);
    });

    it('Login with capital letters- Return a 200', function (done) {
        request(app).post('/api/login').send(users.validUser3).expect(200).end(done);
    });

    it('Login and getting all optional user data', async function () {
        let res = await requestHandler.login(users.validUser);
        res.status.should.equal(200);
        res.body.lang.should.equals('de');
        res.body.languages.length.should.equals(2);
        res.body.languages.should.includes('de');
        res.body.languages.should.includes('en');
        res.body.topics.length.should.equals(2);
        res.body.topics.should.includes('topic1');
        res.body.topics.should.includes('topic21');
        res.body.regions.length.should.equals(2);
        res.body.regions.should.includes('region-1');
        res.body.regions.should.includes('region-3');
        res.body.infoState.should.equals(1);
    });

    it('Login and getting user data', async function () {
        let res = await requestHandler.login(users.validUser2);
        res.status.should.equal(200);
        res.body.lang.should.equals('de');
        res.body.languages.length.should.equals(1);
        res.body.languages.should.includes('en');
        res.body.infoState.should.equals(0);
        res.body.topics.length.should.equals(0);
        res.body.regions.length.should.equals(0);
    });

    it('Logout - Return a 200', function (done) {
        request(app).post('/api/logout').send({}).expect(200).end(done);
    });
});<|endoftext|>


<commit_before>import builtins from "builtin-modules";
import cleanup from "rollup-plugin-cleanup";
import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import executable from "rollup-plugin-executable";
import json from "rollup-plugin-json";
import pkg from "./package.json";

const external = [
  "assert",
  "async_hooks",
  "buffer",
  "child_process",
  "cluster",
  "console",
  "constants",
  "crypto",
  "dgram",
  "dns",
  "domain",
  "events",
  "fs",
  "http",
  "http2",
  "https",
  "inspector",
  "module",
  "net",
  "os",
  "path",
  "perf_hooks",
  "process",
  "punycode",
  "querystring",
  "readline",
  "repl",
  "stream",
  "string_decoder",
  "sys",
  "timers",
  "tls",
  "trace_events",
  "tty",
  "url",
  "util",
  "v8",
  "vm",
  "zlib",

  "levelup",
  "koa",
  "koa-better-router",
  "koa-jwt",
  "leveldown",
  "sd-daemon"
];

export default
  Object.keys(pkg.bin).map(name => {
    return {
      input: `src/${name}-cli.mjs`,
      output: {
        file: pkg.bin[name],
        format: "cjs",
        banner:
          '#!/bin/sh\n":" //# comment; exec /usr/bin/env node --experimental-modules "$0" "$@"',
        interop: false
      },
      external,
      plugins: [
        resolve(),
        commonjs(),
        json({
          preferConst: true,
          compact: true
        }),
        cleanup({
          extensions: ['js','mjs','jsx','tag']
        }),
        executable()
      ]
    };
  });
<commit_msg>chore(rollup): make use of builtins<commit_after>import builtins from "builtin-modules";
import cleanup from "rollup-plugin-cleanup";
import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import executable from "rollup-plugin-executable";
import json from "rollup-plugin-json";
import pkg from "./package.json";

const external = [
  ...builtins,

  "levelup",
  "koa",
  "koa-better-router",
  "koa-jwt",
  "leveldown",
  "sd-daemon"
];

export default
  Object.keys(pkg.bin).map(name => {
    return {
      input: `src/${name}-cli.mjs`,
      output: {
        file: pkg.bin[name],
        format: "cjs",
        banner:
          '#!/bin/sh\n":" //# comment; exec /usr/bin/env node --experimental-modules "$0" "$@"',
        interop: false
      },
      external,
      plugins: [
        resolve(),
        commonjs(),
        json({
          preferConst: true,
          compact: true
        }),
        cleanup({
          extensions: ['js','mjs','jsx','tag']
        }),
        executable()
      ]
    };
  });
<|endoftext|>


<commit_before>var _ = require('lodash');
var path = require('canonical-path');
var log = require('winston');

var AREA_NAMES = {
  api: 'API',
  guide: 'Developer Guide',
  misc: 'Miscellaneous',
  tutorial: 'Tutorial',
  error: 'Error Reference'
};

function getNavGroup(pages, area, pageSorter, pageMapper) {

  var navItems = _(pages)
    // We don't want the child to include the index page as this is already catered for
    .omit(function(page) { return page.id === 'index'; })

    // Apply the supplied sorting function
    .sortBy(pageSorter)

    // Apply the supplied mapping function
    .map(pageMapper)

    .value();

  return {
    name: area.name,
    type: 'group',
    href: area.id,
    navItems: navItems
  };
}

var navGroupMappers = {
  api: function(areaPages, area) {
    var navGroups = _(areaPages)
      .filter('module') // We are not interested in docs that are not in a module

      .groupBy('module')

      .map(function(modulePages, moduleName) {
        log.debug('moduleName: ' + moduleName);
        var navItems = [];
        var modulePage;

        _(modulePages)

          .groupBy('docType')

          .tap(function(docTypes) {
            log.debug(_.keys(docTypes));
            // Extract the module page from the collection
            modulePage = docTypes.module[0];
            delete docTypes.module;
          })

          .forEach(function(sectionPages, sectionName) {

            if ( sectionPages.length > 0 ) {
              // Push a navItem for this section
              navItems.push({
                name: sectionName,
                type: 'section',
                href: path.dirname(sectionPages[0].path)
              });

              // Push the rest of the sectionPages for this section
              _.forEach(sectionPages, function(sectionPage) {

                navItems.push({
                  name: sectionPage.name,
                  href: sectionPage.path,
                  type: sectionPage.docType
                });

              });
            }
          });
        return {
          name: moduleName,
          href: modulePage.path,
          type: 'group',
          navItems: navItems
        };
      })
      .value();
    return navGroups;
  },
  tutorial: function(pages, area) {
    return [getNavGroup(pages, area, 'step', function(page) {
      return {
        name: page.name,
        step: page.step,
        href: page.path,
        type: 'tutorial'
      };
    })];
  },
  error: function(pages, area) {
    return [getNavGroup(pages, area, 'path', function(page) {
      return {
        name: page.name,
        href: page.path,
        type: page.docType === 'errorNamespace' ? 'section' : 'error'
      };
    })];
  },
  pages: function(pages, area) {
    return [getNavGroup(pages, area, 'path', function(page) {
      return {
        name: page.name,
        href: page.path,
        type: 'page'
      };
    })];
  }
};

var outputFolder;

module.exports = {
  name: 'pages-data',
  description: 'This plugin will create a new doc that will be rendered as an angularjs module ' +
               'which will contain meta information about the pages and navigation',
  runAfter: ['adding-extra-docs', 'component-groups-generate'],
  runBefore: ['extra-docs-added'],
  init: function(config) {
    outputFolder = config.rendering.outputFolder;
  },
  process: function(docs) {

    _(docs)
    .filter(function(doc) { return doc.area === 'api'; })
    .filter(function(doc) { return doc.docType === 'module'; })
    .map(function(doc) { return _.pick(doc, ['id', 'module', 'docType', 'area']); })
    .tap(function(docs) {
      log.debug(docs);
    });

    // We are only interested in docs that are in a area and not landing pages
    var navPages = _.filter(docs, function(page) {
      return page.area &&
        page.docType != 'componentGroup';
    });

    // Generate an object collection of pages that is grouped by area e.g.
    // - area "api"
    //  - group "ng"
    //    - section "directive"
    //    - ngApp
    //    - ngBind
    //    - section "global"
    //    - angular.element
    //    - angular.bootstrap
    //    - section "service"
    //    - $compile
    //  - group "ngRoute"
    //    - section "directive"
    //    - ngView
    //    - section "service"
    //    - $route
    //
    var areas = {};
    _(navPages)
      .groupBy('area')
      .forEach(function(pages, areaId) {
        var area = {
          id: areaId,
          name: AREA_NAMES[areaId]
        };
        areas[areaId] = area;

        var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
        area.navGroups = navGroupMapper(pages, area);
      });

    _.forEach(docs, function(doc) {
      if ( !doc.path ) {
        log.warn('Missing path property for ', doc.id);
      }
    });

    // Extract a list of basic page information for mapping paths to paritals and for client side searching
    var pages = _(docs)
      .map(function(doc) {
        var page = _.pick(doc, [
          'docType', 'id', 'name', 'area', 'outputPath', 'path', 'searchTerms'
        ]);
        return page;
      })
      .indexBy('path')
      .value();

    var docData = {
      docType: 'pages-data',
      id: 'pages-data',
      template: 'pages-data.template.js',
      outputPath: 'js/pages-data.js',

      areas: areas,
      pages: pages
    };
    docs.push(docData);
  }
};
<commit_msg>chore(doc-gen): improve grouping and sorting of api nav items<commit_after>var _ = require('lodash');
var path = require('canonical-path');
var log = require('winston');

var AREA_NAMES = {
  api: 'API',
  guide: 'Developer Guide',
  misc: 'Miscellaneous',
  tutorial: 'Tutorial',
  error: 'Error Reference'
};

function getNavGroup(pages, area, pageSorter, pageMapper) {

  var navItems = _(pages)
    // We don't want the child to include the index page as this is already catered for
    .omit(function(page) { return page.id === 'index'; })

    // Apply the supplied sorting function
    .sortBy(pageSorter)

    // Apply the supplied mapping function
    .map(pageMapper)

    .value();

  return {
    name: area.name,
    type: 'group',
    href: area.id,
    navItems: navItems
  };
}

var navGroupMappers = {
  api: function(areaPages, area) {
    var navGroups = _(areaPages)
      .filter('module') // We are not interested in docs that are not in a module

      .groupBy('module')

      .map(function(modulePages, moduleName) {
        log.debug('moduleName: ' + moduleName);
        var navItems = [];
        var modulePage;

        _(modulePages)

          .groupBy('docType')

          .tap(function(docTypes) {
            log.debug(_.keys(docTypes));
            // Extract the module page from the collection
            modulePage = docTypes.module[0];
            delete docTypes.module;
          })

          .tap(function(docTypes) {
            if ( docTypes.input ) {
              docTypes.directive = docTypes.directive || [];
              // Combine input docTypes into directive docTypes
              docTypes.directive = docTypes.directive.concat(docTypes.input);
              delete docTypes.input;
            }
          })

          .forEach(function(sectionPages, sectionName) {

            sectionPages = _.sortBy(sectionPages, 'name');

            if ( sectionPages.length > 0 ) {
              // Push a navItem for this section
              navItems.push({
                name: sectionName,
                type: 'section',
                href: path.dirname(sectionPages[0].path)
              });

              // Push the rest of the sectionPages for this section
              _.forEach(sectionPages, function(sectionPage) {

                navItems.push({
                  name: sectionPage.name,
                  href: sectionPage.path,
                  type: sectionPage.docType
                });

              });
            }
          });
        return {
          name: moduleName,
          href: modulePage.path,
          type: 'group',
          navItems: navItems
        };
      })
      .value();
    return navGroups;
  },
  tutorial: function(pages, area) {
    return [getNavGroup(pages, area, 'step', function(page) {
      return {
        name: page.name,
        step: page.step,
        href: page.path,
        type: 'tutorial'
      };
    })];
  },
  error: function(pages, area) {
    return [getNavGroup(pages, area, 'path', function(page) {
      return {
        name: page.name,
        href: page.path,
        type: page.docType === 'errorNamespace' ? 'section' : 'error'
      };
    })];
  },
  pages: function(pages, area) {
    return [getNavGroup(pages, area, 'path', function(page) {
      return {
        name: page.name,
        href: page.path,
        type: 'page'
      };
    })];
  }
};

var outputFolder;

module.exports = {
  name: 'pages-data',
  description: 'This plugin will create a new doc that will be rendered as an angularjs module ' +
               'which will contain meta information about the pages and navigation',
  runAfter: ['adding-extra-docs', 'component-groups-generate'],
  runBefore: ['extra-docs-added'],
  init: function(config) {
    outputFolder = config.rendering.outputFolder;
  },
  process: function(docs) {

    _(docs)
    .filter(function(doc) { return doc.area === 'api'; })
    .filter(function(doc) { return doc.docType === 'module'; })
    .map(function(doc) { return _.pick(doc, ['id', 'module', 'docType', 'area']); })
    .tap(function(docs) {
      log.debug(docs);
    });

    // We are only interested in docs that are in a area and not landing pages
    var navPages = _.filter(docs, function(page) {
      return page.area &&
        page.docType != 'componentGroup';
    });

    // Generate an object collection of pages that is grouped by area e.g.
    // - area "api"
    //  - group "ng"
    //    - section "directive"
    //    - ngApp
    //    - ngBind
    //    - section "global"
    //    - angular.element
    //    - angular.bootstrap
    //    - section "service"
    //    - $compile
    //  - group "ngRoute"
    //    - section "directive"
    //    - ngView
    //    - section "service"
    //    - $route
    //
    var areas = {};
    _(navPages)
      .groupBy('area')
      .forEach(function(pages, areaId) {
        var area = {
          id: areaId,
          name: AREA_NAMES[areaId]
        };
        areas[areaId] = area;

        var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
        area.navGroups = navGroupMapper(pages, area);
      });

    _.forEach(docs, function(doc) {
      if ( !doc.path ) {
        log.warn('Missing path property for ', doc.id);
      }
    });

    // Extract a list of basic page information for mapping paths to paritals and for client side searching
    var pages = _(docs)
      .map(function(doc) {
        var page = _.pick(doc, [
          'docType', 'id', 'name', 'area', 'outputPath', 'path', 'searchTerms'
        ]);
        return page;
      })
      .indexBy('path')
      .value();

    var docData = {
      docType: 'pages-data',
      id: 'pages-data',
      template: 'pages-data.template.js',
      outputPath: 'js/pages-data.js',

      areas: areas,
      pages: pages
    };
    docs.push(docData);
  }
};
<|endoftext|>


<commit_before>import {
  Chart as ChartJS,
  BarController,
  BubbleController,
  DoughnutController,
  LineController,
  PieController,
  PolarAreaController,
  RadarController,
  ScatterController
} from 'chart.js'

import {
  chartCreate,
  chartDestroy,
  chartUpdate,
  getChartData,
  setChartLabels,
  setChartDatasets,
  compareData,
  templateError,
  ChartEmits
} from '../../src/utils'

export function generateChart(chartId, chartType, chartController) {
  return {
    props: {
      chartData: {
        type: Object,
        required: true
      },
      chartOptions: {
        type: Object,
        default: () => {}
      },
      datasetIdKey: {
        type: String,
        default: 'label'
      },
      chartId: {
        type: String,
        default: chartId
      },
      width: {
        type: Number,
        default: 400
      },
      height: {
        type: Number,
        default: 400
      },
      cssClasses: {
        type: String,
        default: ''
      },
      styles: {
        type: Object,
        default: () => {}
      },
      plugins: {
        type: Array,
        default: () => []
      }
    },
    data() {
      return {
        _chart: null
      }
    },
    created() {
      ChartJS.register(chartController)
    },
    mounted() {
      if ('datasets' in this.chartData && this.chartData.datasets.length > 0) {
        chartCreate(this.renderChart, this.chartData, this.chartOptions)
        this.$emit(ChartEmits.ChartRendered)
      }
    },
    watch: {
      chartData(newValue, oldValue) {
        this.chartDataHandler(newValue, oldValue)
      }
    },
    methods: {
      renderChart(data, options) {
        if (this.$data._chart !== null) {
          chartDestroy(this.$data._chart)
          this.$emit(ChartEmits.ChartDestroyed)
        }

        if (!this.$refs.canvas) {
          throw new Error(templateError)
        } else {
          const chartData = getChartData(data, this.datasetIdKey)

          const canvasEl2DContext = this.$refs.canvas.getContext('2d')

          if (canvasEl2DContext !== null) {
            this.$data._chart = new ChartJS(canvasEl2DContext, {
              type: chartType,
              data: chartData,
              options,
              plugins: this.plugins
            })
          }
        }
      },
      chartDataHandler(newValue, oldValue) {
        const newData = { ...newValue }
        const oldData = { ...oldValue }

        if (Object.keys(oldData).length > 0) {
          const chart = this.$data._chart

          const isEqualLabelsAndDatasetsLength = compareData(newData, oldData)

          if (isEqualLabelsAndDatasetsLength && chart !== null) {
            setChartDatasets(chart.data, newData, this.datasetIdKey)

            if (newData.labels !== undefined) {
              setChartLabels(chart, newData.labels)
              this.$emit(ChartEmits.LabelsUpdated)
            }

            chartUpdate(chart)
            this.$emit(ChartEmits.ChartUpdated)
          } else {
            if (chart !== null) {
              chartDestroy(chart)
              this.$emit(ChartEmits.ChartDestroyed)
            }

            chartCreate(this.renderChart, this.chartData, this.chartOptions)
            this.$emit(ChartEmits.ChartRendered)
          }
        } else {
          if (this.$data._chart !== null) {
            chartDestroy(this.$data._chart)
            this.$emit(ChartEmits.ChartDestroyed)
          }

          chartCreate(this.renderChart, this.chartData, this.chartOptions)
          this.$emit(ChartEmits.ChartRendered)
        }
      }
    },
    beforeDestroy() {
      if (this.$data._chart !== null) {
        chartDestroy(this.$data._chart)
        this.$emit(ChartEmits.ChartDestroyed)
      }
    },
    render: function (createElement) {
      return createElement(
        'div',
        {
          style: this.styles,
          class: this.cssClasses
        },
        [
          createElement('canvas', {
            attrs: {
              id: this.chartId,
              width: this.width,
              height: this.height
            },
            ref: 'canvas'
          })
        ]
      )
    }
  }
}

export const Bar = /* #__PURE__ */ generateChart(
  'bar-chart',
  'bar',
  BarController
)

export const Doughnut = /* #__PURE__ */ generateChart(
  'doughnut-chart',
  'doughnut',
  DoughnutController
)

export const Line = /* #__PURE__ */ generateChart(
  'line-chart',
  'line',
  LineController
)

export const Pie = /* #__PURE__ */ generateChart(
  'pie-chart',
  'pie',
  PieController
)

export const PolarArea = /* #__PURE__ */ generateChart(
  'polar-chart',
  'polarArea',
  PolarAreaController
)

export const Radar = /* #__PURE__ */ generateChart(
  'radar-chart',
  'radar',
  RadarController
)

export const Bubble = /* #__PURE__ */ generateChart(
  'bubble-chart',
  'bubble',
  BubbleController
)

export const Scatter = /* #__PURE__ */ generateChart(
  'scatter-chart',
  'scatter',
  ScatterController
)

export default {
  Bar,
  Bubble,
  Doughnut,
  Line,
  Pie,
  PolarArea,
  Radar,
  Scatter,
  generateChart
}
<commit_msg>fix: change legacy chart instance type (#789)<commit_after>import {
  Chart as ChartJS,
  BarController,
  BubbleController,
  DoughnutController,
  LineController,
  PieController,
  PolarAreaController,
  RadarController,
  ScatterController
} from 'chart.js'

import {
  chartCreate,
  chartDestroy,
  chartUpdate,
  getChartData,
  setChartLabels,
  setChartDatasets,
  compareData,
  templateError,
  ChartEmits
} from '../../src/utils'

export function generateChart(chartId, chartType, chartController) {
  let _chart = null

  return {
    props: {
      chartData: {
        type: Object,
        required: true
      },
      chartOptions: {
        type: Object,
        default: () => {}
      },
      datasetIdKey: {
        type: String,
        default: 'label'
      },
      chartId: {
        type: String,
        default: chartId
      },
      width: {
        type: Number,
        default: 400
      },
      height: {
        type: Number,
        default: 400
      },
      cssClasses: {
        type: String,
        default: ''
      },
      styles: {
        type: Object,
        default: () => {}
      },
      plugins: {
        type: Array,
        default: () => []
      }
    },
    created() {
      ChartJS.register(chartController)
    },
    mounted() {
      if ('datasets' in this.chartData && this.chartData.datasets.length > 0) {
        chartCreate(this.renderChart, this.chartData, this.chartOptions)
        this.$emit(ChartEmits.ChartRendered)
      }
    },
    watch: {
      chartData(newValue, oldValue) {
        this.chartDataHandler(newValue, oldValue)
      }
    },
    methods: {
      renderChart(data, options) {
        if (_chart !== null) {
          chartDestroy(_chart)
          this.$emit(ChartEmits.ChartDestroyed)
        }

        if (!this.$refs.canvas) {
          throw new Error(templateError)
        } else {
          const chartData = getChartData(data, this.datasetIdKey)

          const canvasEl2DContext = this.$refs.canvas.getContext('2d')

          if (canvasEl2DContext !== null) {
            _chart = new ChartJS(canvasEl2DContext, {
              type: chartType,
              data: chartData,
              options,
              plugins: this.plugins
            })
          }
        }
      },
      chartDataHandler(newValue, oldValue) {
        const newData = { ...newValue }
        const oldData = { ...oldValue }

        if (Object.keys(oldData).length > 0) {
          const isEqualLabelsAndDatasetsLength = compareData(newData, oldData)

          if (isEqualLabelsAndDatasetsLength && _chart !== null) {
            setChartDatasets(_chart.data, newData, this.datasetIdKey)

            if (newData.labels !== undefined) {
              setChartLabels(_chart, newData.labels)
              this.$emit(ChartEmits.LabelsUpdated)
            }

            chartUpdate(_chart)
            this.$emit(ChartEmits.ChartUpdated)
          } else {
            if (_chart !== null) {
              chartDestroy(_chart)
              this.$emit(ChartEmits.ChartDestroyed)
            }

            chartCreate(this.renderChart, this.chartData, this.chartOptions)
            this.$emit(ChartEmits.ChartRendered)
          }
        } else {
          if (_chart !== null) {
            chartDestroy(_chart)
            this.$emit(ChartEmits.ChartDestroyed)
          }

          chartCreate(this.renderChart, this.chartData, this.chartOptions)
          this.$emit(ChartEmits.ChartRendered)
        }
      }
    },
    beforeDestroy() {
      if (_chart !== null) {
        chartDestroy(_chart)
        this.$emit(ChartEmits.ChartDestroyed)
      }
    },
    render: function (createElement) {
      return createElement(
        'div',
        {
          style: this.styles,
          class: this.cssClasses
        },
        [
          createElement('canvas', {
            attrs: {
              id: this.chartId,
              width: this.width,
              height: this.height
            },
            ref: 'canvas'
          })
        ]
      )
    }
  }
}

export const Bar = /* #__PURE__ */ generateChart(
  'bar-chart',
  'bar',
  BarController
)

export const Doughnut = /* #__PURE__ */ generateChart(
  'doughnut-chart',
  'doughnut',
  DoughnutController
)

export const Line = /* #__PURE__ */ generateChart(
  'line-chart',
  'line',
  LineController
)

export const Pie = /* #__PURE__ */ generateChart(
  'pie-chart',
  'pie',
  PieController
)

export const PolarArea = /* #__PURE__ */ generateChart(
  'polar-chart',
  'polarArea',
  PolarAreaController
)

export const Radar = /* #__PURE__ */ generateChart(
  'radar-chart',
  'radar',
  RadarController
)

export const Bubble = /* #__PURE__ */ generateChart(
  'bubble-chart',
  'bubble',
  BubbleController
)

export const Scatter = /* #__PURE__ */ generateChart(
  'scatter-chart',
  'scatter',
  ScatterController
)

export default {
  Bar,
  Bubble,
  Doughnut,
  Line,
  Pie,
  PolarArea,
  Radar,
  Scatter,
  generateChart
}
<|endoftext|>


<commit_before>var http = require('http');
var browserify = require('browserify');
var React = require('react');
var ReactDOMServer = require('react-dom/server');
var Navigation = require('navigation');
var NavigationShared = require('./NavigationShared');
var Data = require('./Data');

http.createServer(function(req, res) {
    if (handleStatic(req, res))
        return;
    var stateNavigator = NavigationShared.getStateNavigator();
    // Set the Navigation context
    stateNavigator.start(req.url);
    // Get the props data for the active State
    getProps(stateNavigator, function(props) {
        res.setHeader('vary', 'content-type');
        if (req.headers['content-type'] === 'application/json') {
            res.write(JSON.stringify(props));
        } else {
            // Create the Component for the active State
            var component = NavigationShared.createComponent(stateNavigator, props)

${ReactDOMServer.renderToString(component)}

        }
        res.end();
    });
}).listen(8080);

function getProps(stateNavigator, callback) {
    stateNavigator.states.people.getProps = function(data, callback) {
        Data.searchPeople(data.pageNumber, function(people) {
            callback({people: people});
        });
    }
    stateNavigator.states.person.getProps = function(data, callback) {
        Data.getPerson(data.id, function(person) {
            callback({person: person});
        });
    }
    // Return the props data for the active State
    return stateNavigator.stateContext.state.getProps(stateNavigator.stateContext.data, callback);
}

function handleStatic(req, res) {
    if (req.url === '/favicon.ico') {
        res.statusCode = 404;
        res.end();
        return true;
    }
    if (req.url === '/app.js') {
        browserify('./NavigationClient.js', {standalone: 'NavigationClient'})
            .bundle()
            .pipe(res)
        return true;
    }
    return false;
}

function safeStringify(props) {
  return JSON.stringify(props).replace(/<\/script/g, '<\\/script').replace(/


<commit_before>import { Plug } from 'mindtouch-http.js/plug.js';
import { Settings } from './lib/settings.js';
import { modelParser } from './lib/modelParser.js';
import { utility } from './lib/utility.js';
import { apiErrorModel } from './models/apiError.model.js';
import { siteJobModel, siteJobsModel } from './models/siteJob.model.js';

const _errorParser = modelParser.createParser(apiErrorModel);

export class SiteJob {

    /**
     * Create a new SiteJob
     * @param {String} jobId The GUID job ID.
     * @param {Settings} [settings] The martian settings that will direct the requests for this instance.
     */
    constructor(jobId, settings = new Settings()) {
        if(!jobId || typeof jobId !== 'string') {
            throw new Error('The job ID must be supplied as a GUID string.');
        }
        this._plug = new Plug(settings.host, settings.plugConfig).at('@api', 'deki', 'site', 'jobs', jobId);
    }

    /**
     *
     */
    getStatus() {
        return this._plug.at('status').get()
            .catch((err) => Promise.reject(_errorParser(err)))
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }

    /**
     * Cancel the site job.
     * @returns {Promise} A promise that, when resolved, indicates the job was successfully cancelled.
     */
    cancel() {
        return this._plug.at('cancel').post()
            .catch((err) => Promise.reject(_errorParser(err)))
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }
}

export class SiteJobManager {

    /**
     * Create a new SiteJobManager object.
     * @param {Settings} [settings] - The martian settings that will direct the requests for this instance.
     */
    constructor(settings = new Settings()) {
        this._plug = new Plug(settings.host, settings.plugConfig).at('@api', 'deki', 'site', 'jobs');
    }

    /**
     * Schedules a site export.
     * @param {Object} options - Options to configure the export job.
     * @param {String} [options.email] - The email address to notify when the job completes. Required if a URL is not supplied.
     * @param {String} [options.url] - The URL to notify when the job completes. Required if an email address is not supplied.
     * @param {Object[]} [options.pages] - An array of objects with information about the pages to export.
     * @param {Number} [options.pages[].id] - The ID of a page to export. Required if the path is not supplied.
     * @param {String} [options.pages[].path] - The path of a page to export. Required if the ID is not supplied.
     * @param {Boolean} [options.pages[].includeSubpages] - Idicates whether or not to export the subpages of the specified page.
     * @returns {Promise.<Object>} - A Promise that will be resolved with the scheduled job info, or rejected with an error specifying the reason for rejection.
     */
    scheduleExport(options) {
        if(!options) {
            return Promise.reject(new Error('The export options must be supplied'));
        }
        let notificationSupplied = false;
        if('email' in options) {
            notificationSupplied = true;
        }
        if('url' in options) {
            notificationSupplied = true;
        }
        if(notificationSupplied === false) {
            return Promise.reject(new Error('Notification email and url are missing. Need an email or url to notify when the job completes.'));
        }
        if('pages' in options) {
            if(!Array.isArray(options.pages)) {
                return Promise.reject('The pages option must be an array.');
            }
        } else {
            return Promise.reject('One or more pages must be specified for export.');
        }
        const pagesElements = options.pages.reduce((acc, page) => {
            let element = '<page';
            if(page.id) {
                element += ` id="${page.id}"`;
            }
            if('includeSubpages' in page) {
                element += ` includesubpages="${page.includeSubpages}"`;
            }
            element += '>';
            if(page.path) {
                element += `<path>${page.path}</path>`;
            }
            element += '</page>';
            return acc + element;
        }, '');
        let postData = '<job><notification>';
        if(options.email) {
            postData += `<email>${options.email}</email>`;
        }
        if(options.url) {
            postData += `<url>${options.url}</url>`;
        }
        postData += '</notification>';
        postData += `<pages>${pagesElements}</pages>`;
        postData += '</job>';
        return this._plug.at('export').post(postData, utility.xmlRequestType)
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }

    /**
     * Schedules a site import
     * @param {Object} options - Options to configure the import job.
     * @param {Boolean} [options.dryRun=false] - Perform a dry run of the import to diagnose potential content problems.
     * @param {String} [options.email] - The email address to notify when the job completes. Required if a URL is not supplied.
     * @param {String} [options.url] - The URL to notify when the job completes. Required if an email address is not supplied.
     * @param {String} options.archiveUrl - The URL pointing to the archive to import.
     * @returns {Promise.<Object>} - A Promise that will be resolved with the scheduled job info, or rejected with an error specifying the reason for rejection.
     */
    scheduleImport(options) {
        if(!options) {
            return Promise.reject(new Error('The export options must be supplied'));
        }
        let notificationSupplied = false;
        if('email' in options) {
            notificationSupplied = true;
        }
        if('url' in options) {
            notificationSupplied = true;
        }
        if(notificationSupplied === false) {
            return Promise.reject(new Error('Notification email and url are missing. Need an email or url to notify when the job completes.'));
        }
        if(typeof options.archiveUrl !== 'string' || options.archiveUrl === '') {
            return Promise.reject(new Error('An archive url is required, and must be a non-empty string to perform an import.'));
        }
        let postData = '<job><notification>';
        if(options.email) {
            postData += `<email>${options.email}</email>`;
        }
        if(options.url) {
            postData += `<url>${options.url}</url>`;
        }
        postData += '</notification>';
        postData += `<archive><url>${options.archiveUrl}</url></archive>`;
        postData += '</job>';
        return this._plug.at('import').withParam('dryrun', Boolean(options.dryRun)).post(postData, utility.xmlRequestType)
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }

    /**
     * Gets the job statuses for a site.
     * @returns {Promise.<Object>} - A Promise that will be resolved with the jobs status info, or rejected with an error specifying the reason for rejection.
     */
    getJobsStatuses() {
        return this._plug.at('status').get()
            .catch((err) => Promise.reject(_errorParser(err)))
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobsModel));
    }
}
<commit_msg>Add documentation<commit_after>import { Plug } from 'mindtouch-http.js/plug.js';
import { Settings } from './lib/settings.js';
import { modelParser } from './lib/modelParser.js';
import { utility } from './lib/utility.js';
import { apiErrorModel } from './models/apiError.model.js';
import { siteJobModel, siteJobsModel } from './models/siteJob.model.js';

const _errorParser = modelParser.createParser(apiErrorModel);

export class SiteJob {

    /**
     * Create a new SiteJob
     * @param {String} jobId The GUID job ID.
     * @param {Settings} [settings] The martian settings that will direct the requests for this instance.
     */
    constructor(jobId, settings = new Settings()) {
        if(!jobId || typeof jobId !== 'string') {
            throw new Error('The job ID must be supplied as a GUID string.');
        }
        this._plug = new Plug(settings.host, settings.plugConfig).at('@api', 'deki', 'site', 'jobs', jobId);
    }

    /**
     * Get the status information for the job.
     * @returns {Promise} A promise that, when resolved, contains the job's status information.
     */
    getStatus() {
        return this._plug.at('status').get()
            .catch((err) => Promise.reject(_errorParser(err)))
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }

    /**
     * Cancel the site job.
     * @returns {Promise} A promise that, when resolved, contains the job's status information.
     */
    cancel() {
        return this._plug.at('cancel').post()
            .catch((err) => Promise.reject(_errorParser(err)))
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }
}

export class SiteJobManager {

    /**
     * Create a new SiteJobManager object.
     * @param {Settings} [settings] - The martian settings that will direct the requests for this instance.
     */
    constructor(settings = new Settings()) {
        this._plug = new Plug(settings.host, settings.plugConfig).at('@api', 'deki', 'site', 'jobs');
    }

    /**
     * Schedules a site export.
     * @param {Object} options - Options to configure the export job.
     * @param {String} [options.email] - The email address to notify when the job completes. Required if a URL is not supplied.
     * @param {String} [options.url] - The URL to notify when the job completes. Required if an email address is not supplied.
     * @param {Object[]} [options.pages] - An array of objects with information about the pages to export.
     * @param {Number} [options.pages[].id] - The ID of a page to export. Required if the path is not supplied.
     * @param {String} [options.pages[].path] - The path of a page to export. Required if the ID is not supplied.
     * @param {Boolean} [options.pages[].includeSubpages] - Idicates whether or not to export the subpages of the specified page.
     * @returns {Promise.<Object>} - A Promise that will be resolved with the scheduled job info, or rejected with an error specifying the reason for rejection.
     */
    scheduleExport(options) {
        if(!options) {
            return Promise.reject(new Error('The export options must be supplied'));
        }
        let notificationSupplied = false;
        if('email' in options) {
            notificationSupplied = true;
        }
        if('url' in options) {
            notificationSupplied = true;
        }
        if(notificationSupplied === false) {
            return Promise.reject(new Error('Notification email and url are missing. Need an email or url to notify when the job completes.'));
        }
        if('pages' in options) {
            if(!Array.isArray(options.pages)) {
                return Promise.reject('The pages option must be an array.');
            }
        } else {
            return Promise.reject('One or more pages must be specified for export.');
        }
        const pagesElements = options.pages.reduce((acc, page) => {
            let element = '<page';
            if(page.id) {
                element += ` id="${page.id}"`;
            }
            if('includeSubpages' in page) {
                element += ` includesubpages="${page.includeSubpages}"`;
            }
            element += '>';
            if(page.path) {
                element += `<path>${page.path}</path>`;
            }
            element += '</page>';
            return acc + element;
        }, '');
        let postData = '<job><notification>';
        if(options.email) {
            postData += `<email>${options.email}</email>`;
        }
        if(options.url) {
            postData += `<url>${options.url}</url>`;
        }
        postData += '</notification>';
        postData += `<pages>${pagesElements}</pages>`;
        postData += '</job>';
        return this._plug.at('export').post(postData, utility.xmlRequestType)
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }

    /**
     * Schedules a site import
     * @param {Object} options - Options to configure the import job.
     * @param {Boolean} [options.dryRun=false] - Perform a dry run of the import to diagnose potential content problems.
     * @param {String} [options.email] - The email address to notify when the job completes. Required if a URL is not supplied.
     * @param {String} [options.url] - The URL to notify when the job completes. Required if an email address is not supplied.
     * @param {String} options.archiveUrl - The URL pointing to the archive to import.
     * @returns {Promise.<Object>} - A Promise that will be resolved with the scheduled job info, or rejected with an error specifying the reason for rejection.
     */
    scheduleImport(options) {
        if(!options) {
            return Promise.reject(new Error('The export options must be supplied'));
        }
        let notificationSupplied = false;
        if('email' in options) {
            notificationSupplied = true;
        }
        if('url' in options) {
            notificationSupplied = true;
        }
        if(notificationSupplied === false) {
            return Promise.reject(new Error('Notification email and url are missing. Need an email or url to notify when the job completes.'));
        }
        if(typeof options.archiveUrl !== 'string' || options.archiveUrl === '') {
            return Promise.reject(new Error('An archive url is required, and must be a non-empty string to perform an import.'));
        }
        let postData = '<job><notification>';
        if(options.email) {
            postData += `<email>${options.email}</email>`;
        }
        if(options.url) {
            postData += `<url>${options.url}</url>`;
        }
        postData += '</notification>';
        postData += `<archive><url>${options.archiveUrl}</url></archive>`;
        postData += '</job>';
        return this._plug.at('import').withParam('dryrun', Boolean(options.dryRun)).post(postData, utility.xmlRequestType)
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobModel));
    }

    /**
     * Gets the job statuses for a site.
     * @returns {Promise.<Object>} - A Promise that will be resolved with the jobs status info, or rejected with an error specifying the reason for rejection.
     */
    getJobsStatuses() {
        return this._plug.at('status').get()
            .catch((err) => Promise.reject(_errorParser(err)))
            .then((r) => r.json())
            .then(modelParser.createParser(siteJobsModel));
    }
}
<|endoftext|>


<commit_before>/*
 dk.PINCH.S( 'test', function( $e ){
 log( 'site pinch ---------------------------------' );
 log( 'type : ' + $e.type );
 log( 'scale : ' + $e.scale );
 log( 'distance : ' + $e.distance );
 log( 'move : ' + $e.moveX + ' , ' + $e.moveY );
 log( 'center : ' + $e.centerX + ' , ' + $e.centerY );
 } )
 $e.type
 oneStart, one, oneEnd, pinchStart, pinch, pinchEnd
 */
dk.obj( 'PINCH', (function( $sList, $dkMouse, $dkEvent ){
	var r, func, start, end, mPow = Math.pow, mSqrt = Math.sqrt, mMax = Math.max, mMin = Math.min, mAbs = Math.abs,
		getDistance, reset, startFlag = false, initFlag = false, oldScale, initD, init, pinchFlag = false, initOne = {}, initPinch = {}, count = 0;

	getDistance = function( $p0, $p1 ){ return ~~mSqrt( mPow( $p0.x - $p1.x, 2 ) + mPow( $p0.y - $p1.y, 2 ) ); },
		reset = function( $ev ){ $ev.distance = 0, $ev.moveX = 0, $ev.moveY = 0, $ev.scale = 1, oldScale = 1, $ev.centerX = 0, $ev.centerY = 0; },
		init = function( $ev ){ $e.nativeEvent.stopPropagation(), $e.nativeEvent.preventDefault(), $ev.type = 'oneStart', startFlag = true, initFlag = true, reset( $ev ); },

		func = function( $e ){
			var ev = $dkEvent( $e.nativeEvent ), touchList = $dkMouse.touches, leng = touchList.length, point0, point1;

				point0 = { x : touchList[ 0 ].pageX, y : touchList[ 0 ].pageY };

			if( leng == 0 ){
				ev.type = 'oneEnd', startFlag = false, initFlag = false, reset( ev ), r[ 'update' ]( ev ); // oneEnd
			}else if( leng == 1 ){
				if( $e.type == 'move' ){
					if( startFlag ) ev.type = 'one', ev.scale = oldScale, ev.moveX = point0.x - initOne.x, ev.moveY = point0.y - initOne.y, r[ 'update' ]( ev ); // one
					else init( ev ), initOne = point0, r[ 'update' ]( ev ); // oneStart one
				}else if( $e.type == 'up' ){
					if( pinchFlag ) ev.type = 'pinchEnd', initOne = point0, ev.moveX = 0, ev.moveY = 0, r[ 'update' ]( ev ); // pinchEnd
					else ev.type = 'oneEnd', startFlag = false, initFlag = false, reset( ev ), r[ 'update' ]( ev ); // oneEnd
				}
				pinchFlag = false;
			}else if( leng > 1 ){
				if( initFlag ){
					point1 = { x : touchList[ 1 ].pageX, y : touchList[ 1 ].pageY },
						ev.distance = getDistance( point0, point1 ), ev.centerX = mMin( point0.x, point1.x ) + mAbs( point1.x - point0.x ) / 2, ev.centerY = mMin( point0.y, point1.y ) + mAbs( point1.y - point0.y ) / 2;
					if( pinchFlag ){
						ev.type = 'pinch', ev.moveX = ev.centerX - initPinch.x, ev.moveY = ev.centerY - initPinch.y, ev.scale = oldScale = ev.distance / initD; // pinch
					}else{
						ev.type = 'pinchStart', pinchFlag = true, initPinch = { x : ev.centerX, y : ev.centerY }, ev.moveX = 0, ev.moveY = 0, initD = ev.distance, ev.scale = 1; // pinchStart
					}
					r[ 'update' ]( ev );
				}else{
					init( ev ), initOne = point0, r[ 'update' ]( ev ); // oneStart ( safari  ġ  )
				}
			}
		},
		start = function(){ $dkMouse.S( 'dkPinch', func ) },
		end = function(){ $dkMouse.S( 'dkPinch', null ) },
		r = $sList( 'PINCH', 1, start, end )
	return r;
})( dk.sList, dk.MOUSE, dk.dkEvent ) );<commit_msg>dk v0.2.1 pinch<commit_after>/*
 dk.PINCH.S( 'test', function( $e ){
 log( 'site pinch ---------------------------------' );
 log( 'type : ' + $e.type );
 log( 'scale : ' + $e.scale );
 log( 'distance : ' + $e.distance );
 log( 'move : ' + $e.moveX + ' , ' + $e.moveY );
 log( 'center : ' + $e.centerX + ' , ' + $e.centerY );
 } )
 $e.type
 oneStart, one, oneEnd, pinchStart, pinch, pinchEnd
 */
dk.obj( 'PINCH', (function( $sList, $dkMouse, $dkEvent ){
	var r, func, start, end, mPow = Math.pow, mSqrt = Math.sqrt, mMax = Math.max, mMin = Math.min, mAbs = Math.abs,
		getDistance, reset, startFlag = false, initFlag = false, oldScale, initD, init, pinchFlag = false, initOne = {}, initPinch = {}, count = 0;

	getDistance = function( $p0, $p1 ){ return ~~mSqrt( mPow( $p0.x - $p1.x, 2 ) + mPow( $p0.y - $p1.y, 2 ) ); },
		reset = function( $ev ){ $ev.distance = 0, $ev.moveX = 0, $ev.moveY = 0, $ev.scale = 1, oldScale = 1, $ev.centerX = 0, $ev.centerY = 0; },
		init = function( $ev ){ $ev.type = 'oneStart', startFlag = true, initFlag = true, reset( $ev ); },

		func = function( $e ){
			var ev = $dkEvent( $e.nativeEvent ), touchList = $dkMouse.touches, leng = touchList.length, point0, point1;

				point0 = { x : touchList[ 0 ].pageX, y : touchList[ 0 ].pageY };

			if( leng != 0 ) $e.nativeEvent.stopPropagation(), $e.nativeEvent.preventDefault();

			if( leng == 0 ){
				ev.type = 'oneEnd', startFlag = false, initFlag = false, reset( ev ), r[ 'update' ]( ev ); // oneEnd
			}else if( leng == 1 ){
				if( $e.type == 'move' ){
					if( startFlag ) ev.type = 'one', ev.scale = oldScale, ev.moveX = point0.x - initOne.x, ev.moveY = point0.y - initOne.y, r[ 'update' ]( ev ); // one
					else init( ev ), initOne = point0, r[ 'update' ]( ev ); // oneStart one
				}else if( $e.type == 'up' ){
					if( pinchFlag ) ev.type = 'pinchEnd', initOne = point0, ev.moveX = 0, ev.moveY = 0, r[ 'update' ]( ev ); // pinchEnd
					else ev.type = 'oneEnd', startFlag = false, initFlag = false, reset( ev ), r[ 'update' ]( ev ); // oneEnd
				}
				pinchFlag = false;
			}else if( leng > 1 ){
				if( initFlag ){
					point1 = { x : touchList[ 1 ].pageX, y : touchList[ 1 ].pageY },
						ev.distance = getDistance( point0, point1 ), ev.centerX = mMin( point0.x, point1.x ) + mAbs( point1.x - point0.x ) / 2, ev.centerY = mMin( point0.y, point1.y ) + mAbs( point1.y - point0.y ) / 2;
					if( pinchFlag ){
						ev.type = 'pinch', ev.moveX = ev.centerX - initPinch.x, ev.moveY = ev.centerY - initPinch.y, ev.scale = oldScale = ev.distance / initD; // pinch
					}else{
						ev.type = 'pinchStart', pinchFlag = true, initPinch = { x : ev.centerX, y : ev.centerY }, ev.moveX = 0, ev.moveY = 0, initD = ev.distance, ev.scale = 1; // pinchStart
					}
					r[ 'update' ]( ev );
				}else{
					init( ev ), initOne = point0, r[ 'update' ]( ev ); // oneStart ( safari  ġ  )
				}
			}
		},
		start = function(){ $dkMouse.S( 'dkPinch', func ) },
		end = function(){ $dkMouse.S( 'dkPinch', null ) },
		r = $sList( 'PINCH', 1, start, end )
	return r;
})( dk.sList, dk.MOUSE, dk.dkEvent ) );<|endoftext|>


<commit_before>// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */

frappe.query_reports["Supplier Ledger Summary"] = {
	"filters": [
		{
			"fieldname":"company",
			"label": __("Company"),
			"fieldtype": "Link",
			"options": "Company",
			"default": frappe.defaults.get_user_default("Company")
		},
		{
			"fieldname":"from_date",
			"label": __("From Date"),
			"fieldtype": "Date",
			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
			"reqd": 1,
			"width": "60px"
		},
		{
			"fieldname":"to_date",
			"label": __("To Date"),
			"fieldtype": "Date",
			"default": frappe.datetime.get_today(),
			"reqd": 1,
			"width": "60px"
		},
		{
			"fieldname":"finance_book",
			"label": __("Finance Book"),
			"fieldtype": "Link",
			"options": "Finance Book"
		},
		{
			"fieldname":"party",
			"label": __("Customer"),
			"fieldtype": "Link",
			"options": "Customer",
			on_change: () => {
				var party = frappe.query_report.get_filter_value('party');
				if (party) {
					frappe.db.get_value('Supplier', party, ["tax_id", "supplier_name"], function(value) {
						frappe.query_report.set_filter_value('tax_id', value["tax_id"]);
						frappe.query_report.set_filter_value('supplier_name', value["supplier_name"]);
					});
				} else {
					frappe.query_report.set_filter_value('tax_id', "");
					frappe.query_report.set_filter_value('supplier_name', "");
				}
			}
		},
		{
			"fieldname":"supplier_group",
			"label": __("Supplier Group"),
			"fieldtype": "Link",
			"options": "Supplier Group"
		},
		{
			"fieldname":"payment_terms_template",
			"label": __("Payment Terms Template"),
			"fieldtype": "Link",
			"options": "Payment Terms Template"
		},
		{
			"fieldname":"territory",
			"label": __("Territory"),
			"fieldtype": "Link",
			"options": "Territory"
		},
		{
			"fieldname":"sales_partner",
			"label": __("Sales Partner"),
			"fieldtype": "Link",
			"options": "Sales Partner"
		},
		{
			"fieldname":"sales_person",
			"label": __("Sales Person"),
			"fieldtype": "Link",
			"options": "Sales Person"
		},
		{
			"fieldname":"tax_id",
			"label": __("Tax Id"),
			"fieldtype": "Data",
			"hidden": 1
		},
		{
			"fieldname":"supplier_name",
			"label": __("Supplier Name"),
			"fieldtype": "Data",
			"hidden": 1
		}
	]
};
<commit_msg>fix: change customer to supplier<commit_after>// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */

frappe.query_reports["Supplier Ledger Summary"] = {
	"filters": [
		{
			"fieldname":"company",
			"label": __("Company"),
			"fieldtype": "Link",
			"options": "Company",
			"default": frappe.defaults.get_user_default("Company")
		},
		{
			"fieldname":"from_date",
			"label": __("From Date"),
			"fieldtype": "Date",
			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
			"reqd": 1,
			"width": "60px"
		},
		{
			"fieldname":"to_date",
			"label": __("To Date"),
			"fieldtype": "Date",
			"default": frappe.datetime.get_today(),
			"reqd": 1,
			"width": "60px"
		},
		{
			"fieldname":"finance_book",
			"label": __("Finance Book"),
			"fieldtype": "Link",
			"options": "Finance Book"
		},
		{
			"fieldname":"party",
			"label": __("Supplier"),
			"fieldtype": "Link",
			"options": "Supplier",
			on_change: () => {
				var party = frappe.query_report.get_filter_value('party');
				if (party) {
					frappe.db.get_value('Supplier', party, ["tax_id", "supplier_name"], function(value) {
						frappe.query_report.set_filter_value('tax_id', value["tax_id"]);
						frappe.query_report.set_filter_value('supplier_name', value["supplier_name"]);
					});
				} else {
					frappe.query_report.set_filter_value('tax_id', "");
					frappe.query_report.set_filter_value('supplier_name', "");
				}
			}
		},
		{
			"fieldname":"supplier_group",
			"label": __("Supplier Group"),
			"fieldtype": "Link",
			"options": "Supplier Group"
		},
		{
			"fieldname":"payment_terms_template",
			"label": __("Payment Terms Template"),
			"fieldtype": "Link",
			"options": "Payment Terms Template"
		},
		{
			"fieldname":"territory",
			"label": __("Territory"),
			"fieldtype": "Link",
			"options": "Territory"
		},
		{
			"fieldname":"sales_partner",
			"label": __("Sales Partner"),
			"fieldtype": "Link",
			"options": "Sales Partner"
		},
		{
			"fieldname":"sales_person",
			"label": __("Sales Person"),
			"fieldtype": "Link",
			"options": "Sales Person"
		},
		{
			"fieldname":"tax_id",
			"label": __("Tax Id"),
			"fieldtype": "Data",
			"hidden": 1
		},
		{
			"fieldname":"supplier_name",
			"label": __("Supplier Name"),
			"fieldtype": "Data",
			"hidden": 1
		}
	]
};
<|endoftext|>


<commit_before>/**
 * Created by hen on 2/20/14.
 */
    var bbVis, brush, createVis, dataSet, handle, height, margin, svg, svg2, width;

    margin = {
        top: 50,
        right: 50,
        bottom: 50,
        left: 50
    };

    width = 960 - margin.left - margin.right;

    height = 300 - margin.bottom - margin.top;

    bbVis = {
        x: 0 + 100,
        y: 10,
        w: width - 100,
        h: 100
    };

    dataSet = [];

    svg = d3.select("#vis").append("svg").attr({
        width: width + margin.left + margin.right,
        height: height + margin.top + margin.bottom
    }).append("g").attr({
            transform: "translate(" + margin.left + "," + margin.top + ")"
        });

    d3.csv("../data.csv", function(data) {

        dataSet = data;
        console.log(dataSet);

        return createVis();
    });

    createVis = function() {
        var xAxis, xScale, yAxis,  yScale;

          xScale = d3.scale.linear().domain([0,100]).range([0, bbVis.w]);   // define the right domain generically. TODO: get time
          yScale = d3.scale.linear().domain([0,100]).range(0, bbVis.h]);    // define the

		  // example that translates to the bottom left of our vis space:
		  var visFrame = svg.append("g").attr({
		      "transform": "translate(" + bbVis.x + "," + (bbVis.y + bbVis.h) + ")",
		  	  //....

		  });

		  visFrame.append("rect");
		  //....

//        yScale = .. // define the right y domain and range -- use bbVis

//        xAxis = ..
//        yAxis = ..
//        // add y axis to svg !

    };
<commit_msg>Still working on Problem 2<commit_after>/**
 * Created by hen on 2/20/14.
 */
    var bbVis, brush, createVis, dataSet, handle, height, margin, svg, svg2, width;

    margin = {
        top: 50,
        right: 50,
        bottom: 50,
        left: 50
    };

    width = 960 - margin.left - margin.right;

    height = 300 - margin.bottom - margin.top;

    bbVis = {
        x: 0 + 100,
        y: -height,
        w: width - 100,
        h: height
    };

    dataSet = [];

    svg = d3.select("#vis").append("svg").attr({
        width: width + margin.left + margin.right,
        height: height + margin.top + margin.bottom
    }).append("g").attr({
            transform: "translate(" + margin.left + "," + margin.top + ")"
        });

    d3.csv("../data.csv", function(data) {

        dataSet = data;
        console.log(dataSet);

        return createVis();
    });

    createVis = function() {
        var xAxis, xScale, yAxis,  yScale;
        var allPopulationPoints = [];
        var allYears = [];

        // determine maximum and minimum populations

        dataSet.forEach(function(d){allPopulationPoints.push(d.HYDE, d.Maddison, d.PopulationBureau, d.UN, d.USCensus)});
        var maximumPopulation = d3.max(allPopulationPoints, function(d){ if(d!="") return +d });
        var minimumPopulation = d3.min(allPopulationPoints, function(d){ if(d!="") return +d });

        // determine maximum and minimum dates

        dataSet.forEach(function(d){ allYears.push(d.year)});
        var maximumYear = new Date(Date.UTC(0,0,1)).setUTCFullYear( d3.max(allYears, function(d){if(d!="") return +d}));
        var minimumYear = new Date(Date.UTC(0,0,1)).setUTCFullYear( d3.min(allYears, function(d){if(d!="") return +d}));

        // create scales with minimum and maximum values

        xScale = d3.time.scale()
            .domain([minimumYear, maximumYear])
            .range([0, bbVis.w]);
        yScale = d3.scale.linear()
            .range([0, bbVis.h])
            .domain([minimumPopulation, maximumPopulation]);

        // create Axes with scales
        yAxis = d3.svg.axis()
            .scale(yScale)
            .orient("left");
        xAxis = d3.svg.axis()
            .scale(xScale)
            .orient("bottom");

		// example that translates to the bottom left of our vis space:
		var visFrame = svg.append("g").attr({
		    "transform": "translate(" + bbVis.x + "," + (bbVis.y + bbVis.h) + ")",
            "class": "estimates",

		  //....
		});
		  // visFrame.append("rect");
		  //....

        //attach the x
        visFrame.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0, "+bbVis.h+")")
            .call(xAxis)
        .append("text")
            .attr("y", 25)
            .attr("x", width/2)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("Year");

        visFrame.append("g")
            .attr("class", "y axis")
            .call(yAxis)
        .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("Population");

    };
<|endoftext|>


<commit_before>/*
  Demo helper for launching goldfish on a non-sharepoint site (for demo purposes).
*/
var heightOfDemo = document.body.getBoundingClientRect().bottom;

Goldfish.Create({
  menu: 'alternate-tabs',
  css: {
    primary: '#188efb',
    overrides: '#component-ghostpane { background-color: #188efb; } #component-holder { width:100%; } #outer-space { top:0; height:' + heightOfDemo + 'px; } #component, #component-favourites, #component-layout, #component-settings { width: inherit !important; } .goldfishSnapRight #component, .goldfishSnapRight #component-favourites, .goldfishSnapRight #component-layout, .goldfishSnapRight #component-settings { margin-right: -170px; } #component .input input[type="text"] { background-color: #ffffff; }'
  }
});

var clickers = ['dragSnapinGoldfish','dragSnapinGoldfishLayout','dragSnapinGoldfishSettings','dragSnapinGoldfishFavourites'];

/*
 * Resize Snapin - based on the work done by @author https://twitter.com/blurspline / https://github.com/zz85
 * See post @ http://www.lab4games.net/zz85/blog/2014/11/15/resizing-moving-snapping-windows-with-js-css/
 */

"use strict";

(function(namespace, el, ghost, clickers) {
  // Minimum resizable area (width and height)
  var minWidth = 400;
  var minHeight = 400;

  // Thresholds - leave these alone
  var FULLSCREEN_MARGINS = -10;
  var MARGINS = 4;

  // End of what's configurable.
  var clicked = null;
  // Resizing booleans indicating if we are resizing from one of these points
  var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;
  var currentClicker = null;

  var rightScreenEdge, bottomScreenEdge;

  var preSnapped;

  var b, x, y;

  var redraw = false;

  // The app holding div element (that we move to the snappin)
  var pane = document.getElementById(el);
  // The ghost panel demonstrating the drop point for the move
  var ghostpane = document.getElementById(ghost);

  function setBounds(element, x, y, w, h) {
    element.style.left = x + 'px';
    element.style.top = y + 'px';
    element.style.width = w + 'px';
    element.style.height = h + 'px';
  }

  function getCurrentClicker(e) {
    return e.target || e.srcElement;
  }

  function hintHide() {
    ghostpane.style.opacity = 0;
  }

  function onTouchDown(e) {
    onDown(e.touches[0]);
    e.preventDefault();
  }

  function onTouchMove(e) {
    onMove(e.touches[0]);
  }

  function onTouchEnd(e) {
    if (e.touches.length ==0) onUp(e.changedTouches[0]);
  }

  function onMouseDown(e) {
    onDown(e);
    e.preventDefault();
  }

  function onDown(e) {
    ghostpane.style.display = '';

    calc(e);

    var isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;

    clicked = {
      x: x,
      y: y,
      cx: e.clientX,
      cy: e.clientY,
      w: b.width,
      h: b.height,
      currentClicker: getCurrentClicker(e),
      isResizing: isResizing,
      isMoving: !isResizing && canMove(),
      onTopEdge: onTopEdge,
      onLeftEdge: onLeftEdge,
      onRightEdge: onRightEdge,
      onBottomEdge: onBottomEdge
    };
  }

  function canMove() {
    //return x > 0 && x < b.width && y > 0 && y < b.height && y < 30;
    return x > 0 && x < b.width && y > 0 && y < b.height;
  }

  function calc(e) {
    b = pane.getBoundingClientRect();
    x = e.clientX - b.left;
    y = e.clientY - b.top;

    onTopEdge = y < MARGINS;
    onLeftEdge = x < MARGINS;
    onRightEdge = x >= b.width - MARGINS;
    onBottomEdge = y >= b.height - MARGINS;

    rightScreenEdge = window.innerWidth - MARGINS;
    bottomScreenEdge = window.innerHeight - MARGINS;
  }

  var e;

  function onMove(ee) {
    calc(ee);

    e = ee;

    redraw = true;
  }

  function getApplyBounds(el, drop, snapped) {
    var compiledWidth = pane.getBoundingClientRect().width > window.innerWidth ? 500 : pane.getBoundingClientRect().width;
    var region = null;

    if (b.top < MARGINS) {
      region = 'top';
      setBounds(el, 0, 0, window.innerWidth, 500);
    } else if (b.left < MARGINS) {
      region = 'left';
      setBounds(el, 0, 0, compiledWidth, window.innerHeight);
    } else if (b.right > rightScreenEdge) {
      region = 'right';
      setBounds(el, window.innerWidth - compiledWidth, 0, compiledWidth, window.innerHeight);
    } else if (b.bottom > bottomScreenEdge) {
      region = 'bottom';
      setBounds(el, 0, window.innerHeight / 2, window.innerWidth, 500);
    } else {
      if (drop) {
        return null;
      } else {
        hintHide();
        return;
      }
    }

    if (drop) { return { 'region': region, 'snapped': snapped }; }

    el.style.opacity = 0.2;
  }

  function getCursorState() {
    // style cursor
    if (onRightEdge && onBottomEdge || onLeftEdge && onTopEdge) {
      return 'nwse-resize';
    } else if (onRightEdge && onTopEdge || onBottomEdge && onLeftEdge) {
      return 'nesw-resize';
    } else if (onRightEdge || onLeftEdge) {
      return 'ew-resize';
    } else if (onBottomEdge || onTopEdge) {
      return 'ns-resize';
    } else if (canMove()) {
      return 'move';
    } else {
      return 'default';
    }
  }

  function setSnappinClass(region) {
  	const snap = region.charAt(0).toUpperCase() + region.slice(1);
    // We set a spacial class to the containing div so that we can manipulate the css for the snapped layout
  	pane.className = `animated bounceInRight goldfishSnap${snap}`;
  }

  function animate() {
    requestAnimationFrame(animate);

    if (!redraw) return;

    redraw = false;

    if (clicked && clicked.isResizing) {

      if (clicked.onRightEdge) pane.style.width = Math.max(x, minWidth) + 'px';
      if (clicked.onBottomEdge) pane.style.height = Math.max(y, minHeight) + 'px';

      if (clicked.onLeftEdge) {
        var currentWidth = Math.max(clicked.cx - e.clientX  + clicked.w, minWidth);
        if (currentWidth > minWidth) {
          pane.style.width = currentWidth + 'px';
          pane.style.left = e.clientX + 'px';
        }
      }

      if (clicked.onTopEdge) {
        var currentHeight = Math.max(clicked.cy - e.clientY  + clicked.h, minHeight);
        if (currentHeight > minHeight) {
          pane.style.height = currentHeight + 'px';
          pane.style.top = e.clientY + 'px';
        }
      }

      hintHide();

      return;
    }

    if (clicked && clicked.isMoving) {
      getApplyBounds(ghostpane, false, null);

      if (preSnapped) {
        //getApplyBounds(pane, false, null);
        setBounds(pane,
          e.clientX - preSnapped.width / 2,
          e.clientY - Math.min(clicked.y, preSnapped.height),
          preSnapped.width,
          preSnapped.height
        );
        return;
      }

      // moving
      pane.style.top = (e.clientY - clicked.y) + 'px';
      pane.style.left = (e.clientX - clicked.x) + 'px';

      return;
    }

    // This code executes when mouse moves without clicking
    const curs = getCursorState();

    clickers.forEach(function(clicker) {
      // Set the cursor style for the drag to snapin element
      document.getElementById(clicker).style.cursor = curs;
    });
  }

  function onUp(e) {
    calc(e);

    if (clicked && clicked.isMoving) {
      // Snap
      var snapped = {
        width: b.width,
        height: b.height
      };

      var boundParams = getApplyBounds(pane, true, snapped);
      preSnapped = boundParams.snapped;

      setSnappinClass(boundParams.region);
      hintHide();
    }

    clicked = null;

    ghostpane.style.display = 'none';
  }

  function setEventListeners() {
    clickers.forEach(function(clicker) {
      const clickElement = document.getElementById(clicker);

      if (clickElement !== null) {
        // Mouse events
        clickElement.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mousemove', onMove);
        document.addEventListener('mouseup', onUp);

        // Touch events
        clickElement.addEventListener('touchstart', onTouchDown);
        document.addEventListener('touchmove', onTouchMove);
        document.addEventListener('touchend', onTouchEnd);
      }
    });
  }

  namespace.Start = function Start() {
  	if (typeof clickers !== 'undefiend') {
      setEventListeners();
      animate();
  	} else {
  	  console.log('Goldfish.ResizeSnapin Please provide the clickers parameter (array) when calling the ResizeSnappin extension. Exiting...');
  	}
  };

})(Goldfish.ResizeSnapin = Goldfish.ResizeSnapin || {}, 'outer-space', 'component-ghostpane', clickers);

Goldfish.ResizeSnapin.Start();
<commit_msg>Refined Resize snappin code<commit_after>/*
  Demo helper for launching goldfish on a non-sharepoint site (for demo purposes).
*/
var heightOfDemo = document.body.getBoundingClientRect().bottom;

Goldfish.Create({
  menu: 'alternate-tabs',
  css: {
    primary: '#188efb',
    overrides: '#component-ghostpane { background-color: #188efb; } #component-holder { width:100%; } #outer-space { top:0; height:' + heightOfDemo + 'px; } #component, #component-favourites, #component-layout, #component-settings { width: inherit !important; } .goldfishSnapRight #component, .goldfishSnapRight #component-favourites, .goldfishSnapRight #component-layout, .goldfishSnapRight #component-settings { margin-right: -170px; } .goldfishSnapTop #component-tabs, .goldfishSnapBottom #component-tabs, .goldfishSnapLeft #component-tabs { left: 75px; right:inherit; } #component .input input[type="text"] { background-color: #ffffff; }'
  }
});

var clickers = ['dragSnapinGoldfish','dragSnapinGoldfishLayout','dragSnapinGoldfishSettings','dragSnapinGoldfishFavourites'];

/*
 * Resize Snapin - based on the work done by @author https://twitter.com/blurspline / https://github.com/zz85
 * See post @ http://www.lab4games.net/zz85/blog/2014/11/15/resizing-moving-snapping-windows-with-js-css/
 */

"use strict";

(function(namespace, el, ghost, clickers) {
  // Minimum resizable area (width and height)
  var minWidth = 400;
  var minHeight = 400;

  // Thresholds - leave these alone
  var FULLSCREEN_MARGINS = -10;
  var MARGINS = 4;

  // End of what's configurable.
  var clicked = null;
  // Resizing booleans indicating if we are resizing from one of these points
  var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;
  var currentClicker = null;

  var rightScreenEdge, bottomScreenEdge;

  var preSnapped;

  var b, x, y;

  var redraw = false;

  // The app holding div element (that we move to the snappin)
  var pane = document.getElementById(el);
  // The ghost panel demonstrating the drop point for the move
  var ghostpane = document.getElementById(ghost);

  function setBounds(element, x, y, w, h) {
    element.style.left = x + 'px';
    element.style.top = y + 'px';
    element.style.width = w + 'px';
    element.style.height = h + 'px';
  }

  function getCurrentClicker(e) {
    return e.target || e.srcElement;
  }

  function hintHide() {
    ghostpane.style.opacity = 0;
  }

  function onTouchDown(e) {
    onDown(e.touches[0]);
    e.preventDefault();
  }

  function onTouchMove(e) {
    onMove(e.touches[0]);
  }

  function onTouchEnd(e) {
    if (e.touches.length ==0) onUp(e.changedTouches[0]);
  }

  function onMouseDown(e) {
    onDown(e);
    e.preventDefault();
  }

  function onDown(e) {
    ghostpane.style.display = '';

    calc(e);

    var isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;

    clicked = {
      x: x,
      y: y,
      cx: e.clientX,
      cy: e.clientY,
      w: b.width,
      h: b.height,
      currentClicker: getCurrentClicker(e),
      isResizing: isResizing,
      isMoving: !isResizing && canMove(),
      onTopEdge: onTopEdge,
      onLeftEdge: onLeftEdge,
      onRightEdge: onRightEdge,
      onBottomEdge: onBottomEdge
    };
  }

  function canMove() {
    //return x > 0 && x < b.width && y > 0 && y < b.height && y < 30;
    return x > 0 && x < b.width && y > 0 && y < b.height;
  }

  function calc(e) {
    b = pane.getBoundingClientRect();
    x = e.clientX - b.left;
    y = e.clientY - b.top;

    onTopEdge = y < MARGINS;
    onLeftEdge = x < MARGINS;
    onRightEdge = x >= b.width - MARGINS;
    onBottomEdge = y >= b.height - MARGINS;

    rightScreenEdge = window.innerWidth - MARGINS;
    bottomScreenEdge = window.innerHeight - MARGINS;
  }

  var e;

  function onMove(ee) {
    calc(ee);

    e = ee;

    redraw = true;
  }

  function getApplyBounds(el, drop, snapped) {
    var compiledWidth = pane.getBoundingClientRect().width > window.innerWidth ? 500 : pane.getBoundingClientRect().width;
    var region = null;

    if (b.top < MARGINS) {
      region = 'top';
      setBounds(el, 0, 0, window.innerWidth, 500);
    } else if (b.left < MARGINS) {
      region = 'left';
      setBounds(el, 0, 0, compiledWidth, window.innerHeight);
    } else if (b.right > rightScreenEdge) {
      region = 'right';
      setBounds(el, window.innerWidth - compiledWidth, 0, compiledWidth, window.innerHeight);
    } else if (b.bottom > bottomScreenEdge) {
      region = 'bottom';
      setBounds(el, 0, window.innerHeight / 2, window.innerWidth, 500);
    } else {
      if (drop) {
        return null;
      } else {
        hintHide();
        return;
      }
    }

    if (drop) { return { 'region': region, 'snapped': snapped }; }

    el.style.opacity = 0.2;
  }

  function getCursorState() {
    // style cursor
    if (onRightEdge && onBottomEdge || onLeftEdge && onTopEdge) {
      return 'nwse-resize';
    } else if (onRightEdge && onTopEdge || onBottomEdge && onLeftEdge) {
      return 'nesw-resize';
    } else if (onRightEdge || onLeftEdge) {
      return 'ew-resize';
    } else if (onBottomEdge || onTopEdge) {
      return 'ns-resize';
    } else if (canMove()) {
      return 'move';
    } else {
      return 'default';
    }
  }

  function setSnappinClass(region) {
  	const snap = region.charAt(0).toUpperCase() + region.slice(1);
    // We set a spacial class to the containing div so that we can manipulate the css for the snapped layout
  	pane.className = `animated bounceInRight goldfishSnap${snap}`;
  }

  function animate() {
    requestAnimationFrame(animate);

    if (!redraw) return;

    redraw = false;

    if (clicked && clicked.isResizing) {

      if (clicked.onRightEdge) pane.style.width = Math.max(x, minWidth) + 'px';
      if (clicked.onBottomEdge) pane.style.height = Math.max(y, minHeight) + 'px';

      if (clicked.onLeftEdge) {
        var currentWidth = Math.max(clicked.cx - e.clientX  + clicked.w, minWidth);
        if (currentWidth > minWidth) {
          pane.style.width = currentWidth + 'px';
          pane.style.left = e.clientX + 'px';
        }
      }

      if (clicked.onTopEdge) {
        var currentHeight = Math.max(clicked.cy - e.clientY  + clicked.h, minHeight);
        if (currentHeight > minHeight) {
          pane.style.height = currentHeight + 'px';
          pane.style.top = e.clientY + 'px';
        }
      }

      hintHide();

      return;
    }

    if (clicked && clicked.isMoving) {
      getApplyBounds(ghostpane, false, null);

      if (preSnapped) {
        //getApplyBounds(pane, false, null);
        setBounds(pane,
          e.clientX - preSnapped.width / 2,
          e.clientY - Math.min(clicked.y, preSnapped.height),
          preSnapped.width,
          preSnapped.height
        );
        return;
      }

      // moving
      pane.style.top = (e.clientY - clicked.y) + 'px';
      pane.style.left = (e.clientX - clicked.x) + 'px';

      return;
    }

    // This code executes when mouse moves without clicking
    const curs = getCursorState();

    clickers.forEach(function(clicker) {
      // Set the cursor style for the drag to snapin element
      document.getElementById(clicker).style.cursor = curs;
    });
  }

  function onUp(e) {
    calc(e);

    if (clicked && clicked.isMoving) {
      // Snap
      var snapped = {
        width: b.width,
        height: b.height
      };

      var boundParams = getApplyBounds(pane, true, snapped);
      preSnapped = boundParams.snapped;

      setSnappinClass(boundParams.region);
      hintHide();
    }

    clicked = null;

    ghostpane.style.display = 'none';
  }

  function setEventListeners() {
    clickers.forEach(function(clicker) {
      const clickElement = document.getElementById(clicker);

      if (clickElement !== null) {
        // Mouse events
        clickElement.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mousemove', onMove);
        document.addEventListener('mouseup', onUp);

        // Touch events
        clickElement.addEventListener('touchstart', onTouchDown);
        document.addEventListener('touchmove', onTouchMove);
        document.addEventListener('touchend', onTouchEnd);
      }
    });
  }

  namespace.Start = function Start() {
  	if (typeof clickers !== 'undefiend') {
      setEventListeners();
      animate();
  	} else {
  	  console.log('Goldfish.ResizeSnapin Please provide the clickers parameter (array) when calling the ResizeSnappin extension. Exiting...');
  	}
  };

})(Goldfish.ResizeSnapin = Goldfish.ResizeSnapin || {}, 'outer-space', 'component-ghostpane', clickers);

Goldfish.ResizeSnapin.Start();
<|endoftext|>