<commit_before>/*
 * properties.js: Properties for the prompts in jitsu
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

module.exports = {
  inviteCode: {
    name: 'invite code',
    message: 'Invite Code',
    validator: /^\w+$/,
    warning: 'Invite code can only be letters, and numbers'
  },
  askstarter: {
    name: 'askstarter',
    message: 'Would you like to use a node app? (recommended)',
    default: 'yes'
  },
  appname: {
    name: 'appname',
    message: 'Please enter the name you would like to use for your app',
    default: 'myapp'
  },
  snapshot: {
    name: 'snapshot',
    message: 'Snapshot Name',
    validator: /^[\w|\-|\.]+$/,
    warning: 'Snapshot can only be letters, numbers, dashes, and dots',
    default: (function () {
      return '';
    })()
  },
  starter: {
    name: 'starter',
    message: 'Which node app would you like to install?',
    default: 'helloworld'
  },
  proceed: {
    name: 'proceed',
    message: 'Proceed anyway?',
    default: 'no',
    validator: /^y[es]*|n[o]?$/
  },
  yesno: {
    name: 'are you sure?',
    validator: /y[es]?|n[o]?/,
    warning: 'Must respond yes or no',
    default: 'no'
  },
  "start_local": {
    name: 'start_local',
    message: 'Would you like to start this application locally?',
    validator: /y[es]?|n[o]?/,
    warning: 'Must respond yes or no',
    default: 'yes'
  }
};
<commit_msg>[fix] Accept answers besides ye and ys when asking for yes.<commit_after>/*
 * properties.js: Properties for the prompts in jitsu
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

module.exports = {
  inviteCode: {
    name: 'invite code',
    message: 'Invite Code',
    validator: /^\w+$/,
    warning: 'Invite code can only be letters, and numbers'
  },
  askstarter: {
    name: 'askstarter',
    message: 'Would you like to use a node app? (recommended)',
    default: 'yes'
  },
  appname: {
    name: 'appname',
    message: 'Please enter the name you would like to use for your app',
    default: 'myapp'
  },
  snapshot: {
    name: 'snapshot',
    message: 'Snapshot Name',
    validator: /^[\w|\-|\.]+$/,
    warning: 'Snapshot can only be letters, numbers, dashes, and dots',
    default: (function () {
      return '';
    })()
  },
  starter: {
    name: 'starter',
    message: 'Which node app would you like to install?',
    default: 'helloworld'
  },
  proceed: {
    name: 'proceed',
    message: 'Proceed anyway?',
    default: 'no',
    validator: /^y[es]*|n[o]?$/
  },
  yesno: {
    name: 'are you sure?',
    validator: /y[es]*|n[o]?/,
    warning: 'Must respond yes or no',
    default: 'no'
  },
  "start_local": {
    name: 'start_local',
    message: 'Would you like to start this application locally?',
    validator: /y[es]?|n[o]?/,
    warning: 'Must respond yes or no',
    default: 'yes'
  }
};
<|endoftext|>


<commit_before>/**
 * Created by roylee on 18/05/2015.
 */

var $ =  {
  hubConnection: createMockHubObject
};

function createMockHubObject () {
  'use strict';

  var hub = {
    createHubProxy: function (hubName) {
      return new HubProxy(hubName);
    },
    start: function(transObj) {},
    stop: function() {}
  };

  return hub;
}

function HubProxy ( hubName ) {
  'use strict';

  this._listeners = {};

  this.on = function (ev, fn) {
    this._listeners[ev] = fn;
  };

  this.invoke = function (ev, data) {
    var listener = this._listeners[ev];
    if(typeof listener === 'function') {
      listener.apply(null, Array.prototype.slice.call(arguments, 1));
    }
  };
}

<commit_msg>updated mock defintions<commit_after>/**
 * Created by roylee on 18/05/2015.
 */

var $ =  {
  hubConnection: createMockHubObject
};

function createMockHubObject () {
  'use strict';

  var connection = {
    _err_fn: function(){},
    createHubProxy: function (hubName) {
      return new HubProxy(hubName);
    },
    start: function(transObj) {},
    stop: function() {},
    error: function(err_fn) {
      this._err_fn = err_fn;
    },
    throwErr: function(error) {
      if(typeof this._err_fn === 'function') {
        this._err_fn(error);
      }
    }
  };

  return connection;
}

function HubProxy ( hubName ) {
  'use strict';

  this._listeners = {};

  this.on = function (ev, fn) {
    this._listeners[ev] = fn;
  };

  this.invoke = function (ev, data) {
    var listener = this._listeners[ev];
    if(typeof listener === 'function') {
      listener.apply(null, Array.prototype.slice.call(arguments, 1));
    }
  };
}

<|endoftext|>


<commit_before>(function () {
    'use strict';

    /**
     * @ngdoc function
     * @name lurinfacts.controller:addImages
     * @description
     * # MapCtrl
     * Controller of lurinfacts
     */
    angular.module('lurinfacts')
        .controller('AddImageCtrl', function ($scope, ImageResizeService, ImageLocationService, GeoLocationService, NotificationService, uiGmapGoogleMapApi) {
            var vm = this;
            vm.newPoint = {};
            vm.map = {};

            vm.marker = {
                key: new Date().getTime()
            };
            vm.markerevents = {
                dragend: function (marker) {
                    console.log('marker dragged');
                    var lat = marker.getPosition().lat();
                    var lon = marker.getPosition().lng();
                    var coords = {
                        latitude: lat,
                        longitude: lon
                    };
                    vm.SetMarker(coords);
                    vm.updateLocationByCoords(coords);
                }
            };

            vm.reset = function () {
                vm.map = {
                    options: {},
                    center: {
                        latitude: 47,
                        longitude: 9
                    }
                };
                vm.newPoint = {
                    funFact: '',
                    imageTitle: '',
                    location: {},
                    insertTime : new Date().getTime()
                };
                vm.imageThumb = null;
                vm.imageSource = null;
            };

            vm.SetMarker = function (coords) {
                vm.marker = {
                    coords: coords,
                    key: new Date().getTime()
                };
            };
            vm.SetMap = function (coords) {
                uiGmapGoogleMapApi.then(function () {
                    vm.map.center = {
                        latitude: coords.latitude,
                        longitude: coords.longitude
                    };
                    vm.map.zoom = 5;
                });
                console.log('new marker position');
            };

            vm.currentPositionLoaded = function (position) {
                vm.updateLocationByCoords(position.coords);
                vm.SetMap(position.coords);
            };

            vm.updateLocationByCoords = function (coords) {
                GeoLocationService.getPositionByCoords(coords.latitude, coords.longitude).then(function (location) {
                    vm.newPoint.location = location;
                }, function (error) {
                    NotificationService.error('lurin hacked the application, something went druing address lookup.');
                    console.log('error on getPositionByCoords: ' + error);
                });
            };

            vm.getPositionByAddress = function () {
                GeoLocationService.getPositionByAddress(vm.newPoint.location.address).then(function (location) {
                    vm.newPoint.location = location;
                    var coords = {
                        latitude: location.latitude,
                        longitude: location.longitude
                    };
                    vm.SetMap(coords);
                    vm.SetMarker(coords);

                }, function (error) {
                    NotificationService.error('lurin hacked the application, something went druing address lookup.');
                    console.log('error on getPositionByAddress: ' + error);
                });
            };

            vm.uploadedFileChanged = function (el) {
                var f = el.files[0];
                var reader = new FileReader();
                reader.onload = (function () {
                    console.log('file read');
                    return function () {
                        //vm.imageSource = reader.result;
                        var promiseThumb = ImageResizeService.resize(reader.result, 200);
                        promiseThumb.then(function (img) {
                            vm.imageThumb = img;
                            console.log('thumb created');
                            // $scope.$apply();
                        }, function (reason) {
                            console.log('thumb create failed: ' + reason);
                        });
                        var promise = ImageResizeService.resize(reader.result, 1024);
                        promise.then(function (img) {
                            vm.imageSource = img;
                            console.log('image created');
                            // $scope.$apply();
                        }, function (reason) {
                            console.log('image created failed: ' + reason);
                        });
                    };
                })(f);
                reader.readAsDataURL(f);
            };
            vm.imagesLoaded = function () {
                return vm.imageThumb && vm.imageSource;

            };

            vm.SavePicture = function () {
                console.log('start saving everything');
                ImageLocationService.saveLocation(vm.newPoint, vm.imageSource, vm.imageThumb).then(function (data) {
                    console.log('everything saved under: ' + data[0]);
                    NotificationService.success('image successfully saved!');
                    vm.reset();
                }, function (error) {
                    console.log('error during save: ' + error);
                    NotificationService.error('lurin hacked the application, something went wrong during save.');
                });
            };

            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(vm.currentPositionLoaded);
            } else {
                vm.getPositionByAddress('schilthorn, mürren');
            }

            vm.reset();
        });
}());<commit_msg>Default marker<commit_after>(function () {
    'use strict';

    /**
     * @ngdoc function
     * @name lurinfacts.controller:addImages
     * @description
     * # MapCtrl
     * Controller of lurinfacts
     */
    angular.module('lurinfacts')
        .controller('AddImageCtrl', function ($scope, ImageResizeService, ImageLocationService, GeoLocationService, NotificationService, uiGmapGoogleMapApi) {
            var vm = this;
            vm.newPoint = {};
            vm.map = {};

            vm.marker = {
                key: new Date().getTime()
            };
            vm.markerevents = {
                dragend: function (marker) {
                    console.log('marker dragged');
                    var lat = marker.getPosition().lat();
                    var lon = marker.getPosition().lng();
                    var coords = {
                        latitude: lat,
                        longitude: lon
                    };
                    vm.SetMarker(coords);
                    vm.updateLocationByCoords(coords);
                }
            };

            vm.reset = function () {
                vm.map = {
                    options: {},
                    center: {
                        latitude: 47,
                        longitude: 9
                    }
                };
                vm.newPoint = {
                    funFact: '',
                    imageTitle: '',
                    location: {},
                    insertTime : new Date().getTime()
                };
                vm.imageThumb = null;
                vm.imageSource = null;
                vm.SetMarker({
                        latitude: 47,
                        longitude: 9
                    });
            };

            vm.SetMarker = function (coords) {
                vm.marker = {
                    coords: coords,
                    key: new Date().getTime()
                };
            };
            vm.SetMap = function (coords) {
                uiGmapGoogleMapApi.then(function () {
                    vm.map.center = {
                        latitude: coords.latitude,
                        longitude: coords.longitude
                    };
                    vm.map.zoom = 5;
                });
                console.log('new marker position');
            };

            vm.currentPositionLoaded = function (position) {
                vm.updateLocationByCoords(position.coords);
                vm.SetMap(position.coords);
            };

            vm.updateLocationByCoords = function (coords) {
                GeoLocationService.getPositionByCoords(coords.latitude, coords.longitude).then(function (location) {
                    vm.newPoint.location = location;
                }, function (error) {
                    NotificationService.error('lurin hacked the application, something went druing address lookup.');
                    console.log('error on getPositionByCoords: ' + error);
                });
            };

            vm.getPositionByAddress = function () {
                GeoLocationService.getPositionByAddress(vm.newPoint.location.address).then(function (location) {
                    vm.newPoint.location = location;
                    var coords = {
                        latitude: location.latitude,
                        longitude: location.longitude
                    };
                    vm.SetMap(coords);
                    vm.SetMarker(coords);

                }, function (error) {
                    NotificationService.error('lurin hacked the application, something went druing address lookup.');
                    console.log('error on getPositionByAddress: ' + error);
                });
            };

            vm.uploadedFileChanged = function (el) {
                var f = el.files[0];
                var reader = new FileReader();
                reader.onload = (function () {
                    console.log('file read');
                    return function () {
                        //vm.imageSource = reader.result;
                        var promiseThumb = ImageResizeService.resize(reader.result, 200);
                        promiseThumb.then(function (img) {
                            vm.imageThumb = img;
                            console.log('thumb created');
                            // $scope.$apply();
                        }, function (reason) {
                            console.log('thumb create failed: ' + reason);
                        });
                        var promise = ImageResizeService.resize(reader.result, 1024);
                        promise.then(function (img) {
                            vm.imageSource = img;
                            console.log('image created');
                            // $scope.$apply();
                        }, function (reason) {
                            console.log('image created failed: ' + reason);
                        });
                    };
                })(f);
                reader.readAsDataURL(f);
            };
            vm.imagesLoaded = function () {
                return vm.imageThumb && vm.imageSource;

            };

            vm.SavePicture = function () {
                console.log('start saving everything');
                ImageLocationService.saveLocation(vm.newPoint, vm.imageSource, vm.imageThumb).then(function (data) {
                    console.log('everything saved under: ' + data[0]);
                    NotificationService.success('image successfully saved!');
                    vm.reset();
                }, function (error) {
                    console.log('error during save: ' + error);
                    NotificationService.error('lurin hacked the application, something went wrong during save.');
                });
            };

            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(vm.currentPositionLoaded);
            } else {
                vm.getPositionByAddress('schilthorn, mürren');
            }

            vm.reset();
        });
}());
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';

// TODO: WRITE A REACTJS RENDERER TO GENERATE DOCUMENTATION
// OH MY GOD YOU ARE A GENIUS
//   I KISS YOU

function addFileToWrite(files, filename, contents) {
  const lowercaseFilename = filename.toLowerCase();
  if (files[lowercaseFilename]) {
    throw new Error(`The filename ${filename} will already be written into!`);
  }

  files[lowercaseFilename] = {
    filename: filename.replace(/\s+/, '-'),
    contents,
  };
}

function mockPropTypes() {
  const ReactPropTypes = require('react/lib/ReactPropTypes');

  class PropType {
    constructor(type, isRequired = false) {
      this._type = type;

      this._isRequired = !!isRequired;
      if (!isRequired) {
        this.isRequired = new PropType(type, true);
      }
    }

    toString() {
      let req = '';
      if (this._isRequired) {
        req = ' *``` required ```*';
      }

      return `${'```'} ${this._type} ${'```'}${req}`;
    }
  }

  [
    'array',
    'bool',
    'boolean',
    'function',
    'number',
    'object',
    'string',
    'any',
    'element',
    'node',
  ].forEach(type => {
    ReactPropTypes[type] = new PropType(type);
  });

  ReactPropTypes.func = new PropType('function');

  ReactPropTypes.arrayOf = (instanceType) => {
    return new PropType(`array of ${instanceType.displayName || instanceType.name || instanceType._type || instanceType}`);
  };

  ReactPropTypes.instanceOf = (instanceType) => {
    return new PropType(`${instanceType.displayName || instanceType.name || instanceType._type || instanceType}`);
  };

  ReactPropTypes.objectOf = (instanceType) => {
    return new PropType(`object of ${instanceType.displayName || instanceType.name || instanceType._type || instanceType}`);
  };

  ReactPropTypes.oneOf = (values) => {
    return new PropType(`one of [${values.join(', ')}]`);
  };

  ReactPropTypes.oneOfType = (values) => {
    return new PropType(`one of types [${values.map(value => value.displayName || value.name || value._type || value
    ).join(', ')}]`);
  };

  ReactPropTypes.shape = (shape) => {
    return new PropType(`shape of ${JSON.stringify(shape)}`);
  };
}

function buildCategories() {
  const categoryTree = require('./internalComponentCategories');

  const flatCategories = {};

  const rebuiltTree = {
    root: {
      name: null,
      isRoot: true,
      children: [],
    },
  };

  const queue = [{
    name: null,
    parent: null,
    node: {
      treeNode: rebuiltTree.root,
      children: {
        ...categoryTree,
      },
    },
  }];

  while (queue.length > 0) {
    const {
      name: currentName,
      node: {
        treeNode,
        children: nodeChildren,
        },
      } = queue.shift();

    if (nodeChildren) {
      const childNames = Object.keys(nodeChildren);

      for (let i = 0; i < childNames.length; ++i) {
        const childName = childNames[i];

        const childData = nodeChildren[childName];

        const childTreeNode = {
          isRoot: false,
          parent: treeNode,
          name: childName,
          intro: childData.intro,
          data: childData,
          children: [],
        };

        if (flatCategories[childName]) {
          throw new Error('This category already exists...');
        }

        flatCategories[childName] = childTreeNode;

        treeNode.children.push(childTreeNode);

        queue.push({
          parent: currentName,
          name: childName,
          node: {
            ...childData,
            treeNode: childTreeNode,
          },
        });
      }
    }
  }

  return {
    flat: flatCategories,
    tree: rebuiltTree,
  };
}

function writeCategories(allCategories, filesToWrite, prefix) {
  let fileContents = ` > [Wiki](Home) ▸ **Native Components**

# Native Components

These components can be used without needing to require any modules, e.g.

${'```'}js
import React from 'react';

class SomeClass extends React.Component{
  render() {
    return(
      <group>
        <mesh>
          <boxGeometry/>
          <meshBasicMaterial/>
        </mesh>
      </group>
    );
  }
}
${'```'}

## Components
`;

  const categoryStack = [{
    node: allCategories.tree.root,
    indent: -1,
  }];

  while (categoryStack.length > 0) {
    const {
      isTodo,
      node,
      indent,
      } = categoryStack.shift();

    if (node.name !== null) {
      for (let i = 0; i < indent; ++i) {
        fileContents += '  ';
      }

      if (isTodo) {
        fileContents += `* ${node.name}`;
      } else {
        fileContents += `* [[${node.name}]]`;
      }
    }

    const nodeData = node.data;

    if (!node.isComponent && !node.isTodo && !node.isRoot) {
      let nodeFileContents = `> [Wiki](Home) ▸ [[Native Components]] ▸ ${node.name}`;

      if (nodeData) {
        const description = nodeData.description || (nodeData.getDescription && nodeData.getDescription.call(nodeData)) || undefined;
        if (description) {
          nodeFileContents += '\n' + description;
        }
      }

      addFileToWrite(filesToWrite, `${prefix}${node.name}.md`, nodeFileContents);
    }

    const children = node.children;

    let needsColon = false;

    if (nodeData) {
      if (!node.isComponent) {
        const todo = nodeData.TODO;
        if (todo && todo.length > 0) {
          needsColon = true;
          categoryStack.unshift({
            isTodo: true,
            node: {
              name: 'TODO',
              isTodo: true,
              children: todo.map(item => {
                return {
                  isTodo: true,
                  name: item,
                };
              }),
            },
            indent: indent + 1,
          });
        }
      }
    }

    if (children && children.length > 0) {
      needsColon = true;

      for (let i = children.length - 1; i >= 0; --i) {
        const child = children[i];

        categoryStack.unshift({
          isTodo,
          node: child,
          indent: indent + 1,
        });
      }
    }

    if (node.intro && node.intro.length > 0) {
      needsColon = true;
    }

    if (node.name !== null && needsColon) {
      fileContents += `:`;
    }

    if (node.intro) {
      fileContents += ` ${node.intro}.`;
    }

    fileContents += `\n`;
  }

  addFileToWrite(filesToWrite, `${prefix}Native-Components.md`, fileContents);
}

function getComponentInfo(componentName, propTypes) {
  const infoPath = path.join(__dirname, 'internalComponents', `${componentName}.js`);

  if (!fs.existsSync(infoPath)) {
    fs.writeFileSync(infoPath, `import DocInfo from '../DocInfo';

class ${componentName} extends DocInfo {
  getDescription() {
    return ${'``'};
  }

  getAttributesText() {
    return {${Object.keys(propTypes)
      .map(propName => {
        return `
      ${propName}: '',`;
      }).join('')}
    };
  }
}

export default ${componentName};
`, 'utf8');
  }

  return require(infoPath);
}

function writeDescriptors(descriptors, allCategories, filesToWrite, prefix) {
  Object.keys(descriptors).forEach((componentName) => {
    const descriptor = descriptors[componentName];

    const propTypes = descriptor.propTypes;

    const ComponentInfo = getComponentInfo(componentName, propTypes);

    const componentInfo = new ComponentInfo();

    const intro = componentInfo.getIntro();
    const description = componentInfo.getDescription();

    let fileContents = '';

    const category = allCategories.flat[componentName];
    if (!category) {
      console.log('no category found for ', componentName); // eslint-disable-line

      fileContents += `> [Wiki](Home) ▸ [[Native Components]] ▸ **${componentName}**`;
    } else {
      fileContents += `> [Wiki](Home) ▸ [[Native Components]] ▸ `;

      category.isComponent = true;

      const lineage = [];
      let parent = category.parent;

      while (parent) {
        if (parent.name) {
          lineage.push(parent.name);
        }

        parent = parent.parent;
      }

      lineage.reverse();

      fileContents += lineage.map(name => {
        return `[[${name}]] ▸ `;
      }).join('');

      fileContents += `**${componentName}**`;
    }

    let infoString = '';

    if (intro.length > 0) {
      infoString += intro + '.\n';
    }

    if (description.length > 0) {
      infoString += description + '.\n';
    }

    if (infoString.length > 0) {
      infoString = '\n' + infoString;
    }

    fileContents += `

# ${componentName}
${infoString}
`;

    if (descriptor.isResource) {
      // move resourceId prop to the end

      const resourceIdProp = propTypes.resourceId;

      delete propTypes.resourceId;

      propTypes.resourceId = resourceIdProp;
    }

    const propNames = Object.keys(propTypes);

    propNames.sort((a, b) => {
      // have required properties go before the optional ones

      const firstProp = propTypes[a];
      const secondProp = propTypes[b];

      if (firstProp._isRequired === secondProp._isRequired) {
        return 0;
      }

      if (firstProp._isRequired) {
        return -1;
      }

      return 1;
    });

    const attributesText = componentInfo.getAttributesText();

    if (propNames.length > 0) {
      fileContents += '## Attributes\n';

      propNames.forEach((propName, i) => {
        if (i > 0) {
          fileContents += '\n\n';
        }

        fileContents += `### ${propName}
${propTypes[propName].toString()}`;

        const propDescription = attributesText[propName];

        if (propDescription && propDescription.length > 0) {
          fileContents += `: ${propDescription}`;
        }
      });
    }

    if (category) {
      const children = category.children;

      if (children && children.length > 0) {
        fileContents += '\n\n## Children:'; // EOF

        for (let i = 0; i < children.length; ++i) {
          const child = children[i];

          fileContents += `\n  * [[${child.name}]]`;

          if (child.intro) {
            fileContents += `: ${child.intro}.`;
          }
        }
      }
    }

    if (descriptor.isResource) {
      fileContents += '\n\n';

      fileContents += 'This component can be added into <[[resources]]/>! See [[Resource Types]] for more information.';
    }

    fileContents += '\n'; // EOF

    addFileToWrite(filesToWrite, `${prefix}${componentName}.md`, fileContents);
  });
}
function populateCategoryIntros(descriptors, allCategories) {
// populate category intros
  Object.keys(descriptors).forEach((componentName) => {
    const {propTypes, isResource} = descriptors[componentName];

    const ComponentInfo = getComponentInfo(componentName, propTypes);

    const componentInfo = new ComponentInfo();

    const intro = componentInfo.getIntro();

    const category = allCategories.flat[componentName];

    if (!category) {
      console.log('no category found for ', componentName); // eslint-disable-line
    } else {
      category.intro = intro;
    }

    if (isResource) {
      allCategories.flat['Resource Types'].data.resourceTypes.push(category);
    }
  });
}
export default (done) => {
  // mock global variables for three.js
  GLOBAL.self = {};

  // mock global variables for internal component propTypes
  GLOBAL.HTMLCanvasElement = class HTMLCanvasElement {
  };

  const THREE = require('three.js');

  Object.keys(THREE).forEach(key => {
    const value = THREE[key];
    if (value && value.prototype) {
      value.displayName = `THREE.${key}`;
      return;
    }

    THREE[key] = `THREE.${key}`;
  });

  mockPropTypes();

  const allCategories = buildCategories();

  if (!fs.existsSync('docs/generated')) {
    fs.mkdirSync('docs/generated');
  }

  const EDC = require('../../src/ElementDescriptorContainer');

  const {descriptors} = new EDC({});

  populateCategoryIntros(descriptors, allCategories);

  const filesToWrite = {};

  const prefix = 'wiki/';

  writeDescriptors(descriptors, allCategories, filesToWrite, prefix);

  // write categories
  writeCategories(allCategories, filesToWrite, prefix);

  const fileNames = Object.keys(filesToWrite);

  for (let i = 0; i < fileNames.length; ++i) {
    const {filename, contents} = filesToWrite[fileNames[i]];
    fs.writeFileSync(filename, contents, 'utf8');
  }

  done();
};
<commit_msg>[docs] Print lineage for categories too<commit_after>import fs from 'fs';
import path from 'path';

// TODO: WRITE A REACTJS RENDERER TO GENERATE DOCUMENTATION
// OH MY GOD YOU ARE A GENIUS
//   I KISS YOU

function getLineage(category) {
  const lineage = [];
  let parent = category.parent;

  while (parent) {
    if (parent.name) {
      lineage.push(parent.name);
    }

    parent = parent.parent;
  }

  lineage.reverse();
  return lineage;
}

function addFileToWrite(files, filename, contents) {
  const lowercaseFilename = filename.toLowerCase();
  if (files[lowercaseFilename]) {
    throw new Error(`The filename ${filename} will already be written into!`);
  }

  files[lowercaseFilename] = {
    filename: filename.replace(/\s+/, '-'),
    contents,
  };
}

function mockPropTypes() {
  const ReactPropTypes = require('react/lib/ReactPropTypes');

  class PropType {
    constructor(type, isRequired = false) {
      this._type = type;

      this._isRequired = !!isRequired;
      if (!isRequired) {
        this.isRequired = new PropType(type, true);
      }
    }

    toString() {
      let req = '';
      if (this._isRequired) {
        req = ' *``` required ```*';
      }

      return `${'```'} ${this._type} ${'```'}${req}`;
    }
  }

  [
    'array',
    'bool',
    'boolean',
    'function',
    'number',
    'object',
    'string',
    'any',
    'element',
    'node',
  ].forEach(type => {
    ReactPropTypes[type] = new PropType(type);
  });

  ReactPropTypes.func = new PropType('function');

  ReactPropTypes.arrayOf = (instanceType) => {
    return new PropType(`array of ${instanceType.displayName || instanceType.name || instanceType._type || instanceType}`);
  };

  ReactPropTypes.instanceOf = (instanceType) => {
    return new PropType(`${instanceType.displayName || instanceType.name || instanceType._type || instanceType}`);
  };

  ReactPropTypes.objectOf = (instanceType) => {
    return new PropType(`object of ${instanceType.displayName || instanceType.name || instanceType._type || instanceType}`);
  };

  ReactPropTypes.oneOf = (values) => {
    return new PropType(`one of [${values.join(', ')}]`);
  };

  ReactPropTypes.oneOfType = (values) => {
    return new PropType(`one of types [${values.map(value => value.displayName || value.name || value._type || value
    ).join(', ')}]`);
  };

  ReactPropTypes.shape = (shape) => {
    return new PropType(`shape of ${JSON.stringify(shape)}`);
  };
}

function buildCategories() {
  const categoryTree = require('./internalComponentCategories');

  const flatCategories = {};

  const rebuiltTree = {
    root: {
      name: null,
      isRoot: true,
      children: [],
    },
  };

  const queue = [{
    name: null,
    parent: null,
    node: {
      treeNode: rebuiltTree.root,
      children: {
        ...categoryTree,
      },
    },
  }];

  while (queue.length > 0) {
    const {
      name: currentName,
      node: {
        treeNode,
        children: nodeChildren,
        },
      } = queue.shift();

    if (nodeChildren) {
      const childNames = Object.keys(nodeChildren);

      for (let i = 0; i < childNames.length; ++i) {
        const childName = childNames[i];

        const childData = nodeChildren[childName];

        const childTreeNode = {
          isRoot: false,
          parent: treeNode,
          name: childName,
          intro: childData.intro,
          data: childData,
          children: [],
        };

        if (flatCategories[childName]) {
          throw new Error('This category already exists...');
        }

        flatCategories[childName] = childTreeNode;

        treeNode.children.push(childTreeNode);

        queue.push({
          parent: currentName,
          name: childName,
          node: {
            ...childData,
            treeNode: childTreeNode,
          },
        });
      }
    }
  }

  return {
    flat: flatCategories,
    tree: rebuiltTree,
  };
}

function writeCategories(allCategories, filesToWrite, prefix) {
  let fileContents = ` > [Wiki](Home) ▸ **Native Components**

# Native Components

These components can be used without needing to require any modules, e.g.

${'```'}js
import React from 'react';

class SomeClass extends React.Component{
  render() {
    return(
      <group>
        <mesh>
          <boxGeometry/>
          <meshBasicMaterial/>
        </mesh>
      </group>
    );
  }
}
${'```'}

## Components
`;

  const categoryStack = [{
    node: allCategories.tree.root,
    indent: -1,
  }];

  while (categoryStack.length > 0) {
    const {
      isTodo,
      node,
      indent,
      } = categoryStack.shift();

    if (node.name !== null) {
      for (let i = 0; i < indent; ++i) {
        fileContents += '  ';
      }

      if (isTodo) {
        fileContents += `* ${node.name}`;
      } else {
        fileContents += `* [[${node.name}]]`;
      }
    }

    const nodeData = node.data;

    if (!node.isComponent && !node.isTodo && !node.isRoot) {
      let nodeFileContents = `> [Wiki](Home) ▸ [[Native Components]] ▸ `;

      const lineage = getLineage(node);

      nodeFileContents += lineage.map(name => {
        return `[[${name}]] ▸ `;
      }).join('');

      nodeFileContents += `**${node.name}**`;

      if (nodeData) {
        const description = nodeData.description || (nodeData.getDescription && nodeData.getDescription.call(nodeData)) || undefined;
        if (description) {
          nodeFileContents += '\n' + description;
        }
      }

      addFileToWrite(filesToWrite, `${prefix}${node.name}.md`, nodeFileContents);
    }

    const children = node.children;

    let needsColon = false;

    if (nodeData) {
      if (!node.isComponent) {
        const todo = nodeData.TODO;
        if (todo && todo.length > 0) {
          needsColon = true;
          categoryStack.unshift({
            isTodo: true,
            node: {
              name: 'TODO',
              isTodo: true,
              children: todo.map(item => {
                return {
                  isTodo: true,
                  name: item,
                };
              }),
            },
            indent: indent + 1,
          });
        }
      }
    }

    if (children && children.length > 0) {
      needsColon = true;

      for (let i = children.length - 1; i >= 0; --i) {
        const child = children[i];

        categoryStack.unshift({
          isTodo,
          node: child,
          indent: indent + 1,
        });
      }
    }

    if (node.intro && node.intro.length > 0) {
      needsColon = true;
    }

    if (node.name !== null && needsColon) {
      fileContents += `:`;
    }

    if (node.intro) {
      fileContents += ` ${node.intro}.`;
    }

    fileContents += `\n`;
  }

  addFileToWrite(filesToWrite, `${prefix}Native-Components.md`, fileContents);
}

function getComponentInfo(componentName, propTypes) {
  const infoPath = path.join(__dirname, 'internalComponents', `${componentName}.js`);

  if (!fs.existsSync(infoPath)) {
    fs.writeFileSync(infoPath, `import DocInfo from '../DocInfo';

class ${componentName} extends DocInfo {
  getDescription() {
    return ${'``'};
  }

  getAttributesText() {
    return {${Object.keys(propTypes)
      .map(propName => {
        return `
      ${propName}: '',`;
      }).join('')}
    };
  }
}

export default ${componentName};
`, 'utf8');
  }

  return require(infoPath);
}

function writeDescriptors(descriptors, allCategories, filesToWrite, prefix) {
  Object.keys(descriptors).forEach((componentName) => {
    const descriptor = descriptors[componentName];

    const propTypes = descriptor.propTypes;

    const ComponentInfo = getComponentInfo(componentName, propTypes);

    const componentInfo = new ComponentInfo();

    const intro = componentInfo.getIntro();
    const description = componentInfo.getDescription();

    let fileContents = '';

    const category = allCategories.flat[componentName];
    if (!category) {
      console.log('no category found for ', componentName); // eslint-disable-line

      fileContents += `> [Wiki](Home) ▸ [[Native Components]] ▸ **${componentName}**`;
    } else {
      fileContents += `> [Wiki](Home) ▸ [[Native Components]] ▸ `;

      category.isComponent = true;

      const lineage = getLineage(category);

      fileContents += lineage.map(name => {
        return `[[${name}]] ▸ `;
      }).join('');

      fileContents += `**${componentName}**`;
    }

    let infoString = '';

    if (intro.length > 0) {
      infoString += intro + '.\n';
    }

    if (description.length > 0) {
      infoString += description + '.\n';
    }

    if (infoString.length > 0) {
      infoString = '\n' + infoString;
    }

    fileContents += `

# ${componentName}
${infoString}
`;

    if (descriptor.isResource) {
      // move resourceId prop to the end

      const resourceIdProp = propTypes.resourceId;

      delete propTypes.resourceId;

      propTypes.resourceId = resourceIdProp;
    }

    const propNames = Object.keys(propTypes);

    propNames.sort((a, b) => {
      // have required properties go before the optional ones

      const firstProp = propTypes[a];
      const secondProp = propTypes[b];

      if (firstProp._isRequired === secondProp._isRequired) {
        return 0;
      }

      if (firstProp._isRequired) {
        return -1;
      }

      return 1;
    });

    const attributesText = componentInfo.getAttributesText();

    if (propNames.length > 0) {
      fileContents += '## Attributes\n';

      propNames.forEach((propName, i) => {
        if (i > 0) {
          fileContents += '\n\n';
        }

        fileContents += `### ${propName}
${propTypes[propName].toString()}`;

        const propDescription = attributesText[propName];

        if (propDescription && propDescription.length > 0) {
          fileContents += `: ${propDescription}`;
        }
      });
    }

    if (category) {
      const children = category.children;

      if (children && children.length > 0) {
        fileContents += '\n\n## Children:'; // EOF

        for (let i = 0; i < children.length; ++i) {
          const child = children[i];

          fileContents += `\n  * [[${child.name}]]`;

          if (child.intro) {
            fileContents += `: ${child.intro}.`;
          }
        }
      }
    }

    if (descriptor.isResource) {
      fileContents += '\n\n';

      fileContents += 'This component can be added into <[[resources]]/>! See [[Resource Types]] for more information.';
    }

    fileContents += '\n'; // EOF

    addFileToWrite(filesToWrite, `${prefix}${componentName}.md`, fileContents);
  });
}
function populateCategoryIntros(descriptors, allCategories) {
// populate category intros
  Object.keys(descriptors).forEach((componentName) => {
    const {propTypes, isResource} = descriptors[componentName];

    const ComponentInfo = getComponentInfo(componentName, propTypes);

    const componentInfo = new ComponentInfo();

    const intro = componentInfo.getIntro();

    const category = allCategories.flat[componentName];

    if (!category) {
      console.log('no category found for ', componentName); // eslint-disable-line
    } else {
      category.intro = intro;
    }

    if (isResource) {
      allCategories.flat['Resource Types'].data.resourceTypes.push(category);
    }
  });
}
export default (done) => {
  // mock global variables for three.js
  GLOBAL.self = {};

  // mock global variables for internal component propTypes
  GLOBAL.HTMLCanvasElement = class HTMLCanvasElement {
  };

  const THREE = require('three.js');

  Object.keys(THREE).forEach(key => {
    const value = THREE[key];
    if (value && value.prototype) {
      value.displayName = `THREE.${key}`;
      return;
    }

    THREE[key] = `THREE.${key}`;
  });

  mockPropTypes();

  const allCategories = buildCategories();

  if (!fs.existsSync('wiki')) {
    throw new Error('Please load the wiki submodule!');
  }

  const EDC = require('../../src/ElementDescriptorContainer');

  const {descriptors} = new EDC({});

  populateCategoryIntros(descriptors, allCategories);

  const filesToWrite = {};

  const prefix = 'wiki/';

  writeDescriptors(descriptors, allCategories, filesToWrite, prefix);

  // write categories
  writeCategories(allCategories, filesToWrite, prefix);

  const fileNames = Object.keys(filesToWrite);

  for (let i = 0; i < fileNames.length; ++i) {
    const {filename, contents} = filesToWrite[fileNames[i]];
    fs.writeFileSync(filename, contents, 'utf8');
  }

  done();
};
<|endoftext|>


<commit_before>
  basis.require('basis.timer');
  basis.require('basis.dom');
  basis.require('basis.dom.event');
  basis.require('basis.cssom');
  basis.require('basis.layout');
  basis.require('basis.ui.table');

 /**
  * @namespace basis.ui.scrolltable
  */

  var namespace = this.path;

  //
  // import names
  //

  var Class = basis.Class;
  var DOM = basis.dom;
  var cssom = basis.cssom;
  var layout = basis.layout;

  var sender = basis.dom.event.sender;
  var createArray = basis.array.create;

  var Table = basis.ui.table.Table;

  //
  // main part
  //

  function resetStyle(extraStyle){
    return '[style="padding:0!important;margin:0!important;border:0!important;width:auto!important;height:0!important;font-size:0!important;' + (extraStyle || '') + '"]';
  }

  function buildCellsSection(owner, property){
    return DOM.createElement('tbody' + resetStyle(),
      DOM.createElement('tr' + resetStyle(),
        owner.columnWidthSync_.map(Function.getter(property))
      )
    );
  }

  function replaceTemplateNode(owner, refName, newNode){
    DOM.replace(owner.tmpl[refName],
      owner.tmpl[refName] = newNode
    );
  }

  // Cells proto
  // TODO: remove reference to basis.dom.event, because future build improvement may hide basis from global scope
  var measureCell = DOM.createElement('td' + resetStyle(),
    DOM.createElement(resetStyle('position:relative!important'),
      DOM.createElement('iframe[event-load="measureInit"]' + resetStyle('width:100%!important;position:absolute!important;visibility:hidden!important;behavior:expression(basis.dom.event.fireEvent(window,\\"load\\",{type:\\"load\\",target:this}),(runtimeStyle.behavior=\\"none\\"))'))
    )
  );

  var expanderCell = DOM.createElement('td' + resetStyle(),
    DOM.createElement(resetStyle())
  );

 /**
  * @class
  */
  var ScrollTable = Class(Table, {
    className: namespace + '.ScrollTable',

    timer_: false,

   /**
    * Column width sync cells
    */
    columnWidthSync_: null,

   /**
    * @inheritDoc
    */
    template: resource('templates/scrolltable/ScrollTable.tmpl'),

    action: {
      scroll: function(){
        var scrollLeft = -this.tmpl.scrollContainer.scrollLeft + 'px';

        if (this.tmpl.headerOffset.style.left != scrollLeft)
        {
          this.tmpl.headerOffset.style.left = scrollLeft;
          this.tmpl.footerOffset.style.left = scrollLeft;
        }
      },
      measureInit: function(event){
        //console.log('load');
        (sender(event).contentWindow.onresize = this.requestRelayout)();
      }
    },

    headerClass: {
      listen: {
        childNode: {
          '*': function(){
            if (this.owner)
              this.owner.requestRelayout();
          }
        }
      }
    },

   /**
    * @inheritDoc
    */
    init: function(){
      this.requestRelayout = this.requestRelayout.bind(this);
      this.relayout = this.relayout.bind(this);

      // inherit
      Table.prototype.init.call(this);

      // add request to relayout on any header events
      this.header.addHandler({
        '*': this.requestRelayout
      }, this);

      // column width sync cells
      this.columnWidthSync_ = createArray(this.columnCount, function(){
        return {
          measure: measureCell.cloneNode(true),
          header: expanderCell.cloneNode(true),
          footer: expanderCell.cloneNode(true)
        };
      });

      // insert measure row
      replaceTemplateNode(this, 'measureRow', buildCellsSection(this, 'measure'));

      // insert header expander row
      replaceTemplateNode(this, 'headerExpandRow', buildCellsSection(this, 'header'));

      // insert footer expander row
      replaceTemplateNode(this, 'footerExpandRow', buildCellsSection(this, 'footer'));

      //
      layout.addBlockResizeHandler(this.tmpl.boundElement, this.requestRelayout);

      // hack for ie, trigger relayout on create
      if (basis.ua.is('IE8')) // TODO: remove this hack
        setTimeout(this.requestRelayout, 1);
    },

   /**
    * Notify table that it must be relayout.
    */
    requestRelayout: function(){
      if (!this.timer_)
        this.timer_ = setTimeout(this.relayout, 0);
    },

   /**
    * Make relayout of table. Should never be used in common cases. Call requestRelayout instead.
    */
    relayout: function(){
      //console.log('relayout');

      var headerElement = this.header.element;
      var footerElement = this.footer.element;

      //
      // Sync header html
      //
      var headerOuterHTML = DOM.outerHTML(headerElement);
      if (this.shadowHeaderHTML_ != headerOuterHTML)
      {
        this.shadowHeaderHTML_ = headerOuterHTML;
        replaceTemplateNode(this, 'shadowHeader', headerElement.cloneNode(true));
      }

      //
      // Sync footer html
      //
      var footerOuterHTML = DOM.outerHTML(footerElement);
      if (this.shadowFooterHtml_ != footerOuterHTML)
      {
        this.shadowFooterHtml_ = footerOuterHTML;
        replaceTemplateNode(this, 'shadowFooter', footerElement.cloneNode(true));
      }

      //
      // Sync column width
      //
      for (var i = 0, column, columnWidth; column = this.columnWidthSync_[i]; i++)
      {
        columnWidth = column.measure.offsetWidth + 'px';
        cssom.setStyleProperty(column.header.firstChild, 'width', columnWidth);
        cssom.setStyleProperty(column.footer.firstChild, 'width', columnWidth);
        //column.header.firstChild.style.width = columnWidth;
        //column.footer.firstChild.style.width = columnWidth;
      }

      //
      // Calc metrics boxes
      //
      var tableWidth = this.tmpl.boundElement.offsetWidth || 0;
      var headerHeight = headerElement.offsetHeight || 0;
      var footerHeight = footerElement.offsetHeight || 0;

      //
      // Update style properties
      //
      this.tmpl.headerExpandCell.style.left = tableWidth + 'px';
      this.tmpl.footerExpandCell.style.left = tableWidth + 'px';
      this.tmpl.tableElement.style.margin = '-{0}px 0 -{1}px'.format(headerHeight, footerHeight);
      this.element.style.paddingBottom = (headerHeight + footerHeight) + 'px';

      // reset timer
      // it should be at the end of relayout to prevent relayout call while relayout
      this.timer_ = clearTimeout(this.timer_);
    },

   /**
    * @inheritDoc
    */
    destroy: function(){
      this.timer_ = clearTimeout(this.timer_);
      this.timer_ = true; // prevent relayout call

      this.columnWidthSync_ = null;
      this.shadowHeaderHtml_ = null;
      this.shadowFooterHtml_ = null;

      Table.prototype.destroy.call(this);
    }
  });

  //
  // export names
  //

  module.exports = {
    ScrollTable: ScrollTable
  };
<commit_msg>refactoring, use basis.template.define<commit_after>
  basis.require('basis.timer');
  basis.require('basis.dom');
  basis.require('basis.dom.event');
  basis.require('basis.cssom');
  basis.require('basis.layout');
  basis.require('basis.ui.table');

 /**
  * @namespace basis.ui.scrolltable
  */

  var namespace = this.path;

  //
  // import names
  //

  var Class = basis.Class;
  var DOM = basis.dom;
  var cssom = basis.cssom;
  var layout = basis.layout;

  var sender = basis.dom.event.sender;
  var createArray = basis.array.create;
  var createElement = basis.dom.createElement;

  var Table = basis.ui.table.Table;

  //
  // definitions
  //

  var templates = basis.template.define(namespace, {
    ScrollTable: resource('templates/scrolltable/ScrollTable.tmpl')
  });

  //
  // main part
  //

  var IE8 = basis.ua.is('IE8');

  function resetStyle(extraStyle){
    return '[style="padding:0!important;margin:0!important;border:0!important;width:auto!important;height:0!important;font-size:0!important;' + (extraStyle || '') + '"]';
  }

  function buildCellsSection(owner, property){
    return createElement('tbody' + resetStyle(),
      createElement('tr' + resetStyle(),
        owner.columnWidthSync_.map(basis.getter(property))
      )
    );
  }

  function replaceTemplateNode(owner, refName, newNode){
    DOM.replace(owner.tmpl[refName],
      owner.tmpl[refName] = newNode
    );
  }

  // Cells proto
  // TODO: remove reference to basis.dom.event, because future build improvement may hide basis from global scope
  var measureCell = createElement('td' + resetStyle(),
    createElement(resetStyle('position:relative!important'),
      createElement('iframe[event-load="measureInit"]' +
        resetStyle(
          'width:100%!important;position:absolute!important;visibility:hidden!important;' +
          // hack for IE via behavior - load event emulation
          // FIXME: find to better way, but anyway don't access to basis via global scope (it may be removed ob build)
          'behavior:expression(basis.dom.event.fireEvent(window,\\"load\\",{type:\\"load\\",target:this}),(runtimeStyle.behavior=\\"none\\"))'
        )
      )
    )
  );

  var expanderCell = createElement('td' + resetStyle(),
    createElement(resetStyle())
  );

 /**
  * @class
  */
  var ScrollTable = Class(Table, {
    className: namespace + '.ScrollTable',

    timer_: false,

   /**
    * Column width sync cells
    */
    columnWidthSync_: null,

   /**
    * @inheritDoc
    */
    template: templates.ScrollTable,
    action: {
      scroll: function(){
        var scrollLeft = -this.tmpl.scrollContainer.scrollLeft + 'px';

        if (this.tmpl.headerOffset.style.left != scrollLeft)
        {
          this.tmpl.headerOffset.style.left = scrollLeft;
          this.tmpl.footerOffset.style.left = scrollLeft;
        }
      },
      measureInit: function(event){
        (sender(event).contentWindow.onresize = this.requestRelayout)();
      }
    },

    headerClass: {
      listen: {
        childNode: {
          '*': function(){
            if (this.owner)
              this.owner.requestRelayout();
          }
        }
      }
    },

   /**
    * @inheritDoc
    */
    init: function(){
      this.requestRelayout = this.requestRelayout.bind(this);
      this.relayout = this.relayout.bind(this);

      // inherit
      Table.prototype.init.call(this);

      // add request to relayout on any header events
      this.header.addHandler({
        '*': this.requestRelayout
      }, this);

      // column width sync cells
      this.columnWidthSync_ = createArray(this.columnCount, function(){
        return {
          measure: measureCell.cloneNode(true),
          header: expanderCell.cloneNode(true),
          footer: expanderCell.cloneNode(true)
        };
      });

      // insert measure row
      replaceTemplateNode(this, 'measureRow', buildCellsSection(this, 'measure'));

      // insert header expander row
      replaceTemplateNode(this, 'headerExpandRow', buildCellsSection(this, 'header'));

      // insert footer expander row
      replaceTemplateNode(this, 'footerExpandRow', buildCellsSection(this, 'footer'));

      // add block resize trigger
      layout.addBlockResizeHandler(this.tmpl.boundElement, this.requestRelayout);

      // FIXME: hack for ie, trigger relayout on create
      if (IE8)
        setTimeout(this.requestRelayout, 1);
    },

   /**
    * Notify table that it must be relayout.
    */
    requestRelayout: function(){
      if (!this.timer_)
        this.timer_ = setTimeout(this.relayout, 0);
    },

   /**
    * Make relayout of table. Should never be used in common cases. Call requestRelayout instead.
    */
    relayout: function(){
      var headerElement = this.header.element;
      var footerElement = this.footer.element;

      //
      // Sync header html
      //
      var headerOuterHTML = DOM.outerHTML(headerElement);
      if (this.shadowHeaderHTML_ != headerOuterHTML)
      {
        this.shadowHeaderHTML_ = headerOuterHTML;
        replaceTemplateNode(this, 'shadowHeader', headerElement.cloneNode(true));
      }

      //
      // Sync footer html
      //
      var footerOuterHTML = DOM.outerHTML(footerElement);
      if (this.shadowFooterHtml_ != footerOuterHTML)
      {
        this.shadowFooterHtml_ = footerOuterHTML;
        replaceTemplateNode(this, 'shadowFooter', footerElement.cloneNode(true));
      }

      //
      // Sync column width
      //
      for (var i = 0, column, columnWidth; column = this.columnWidthSync_[i]; i++)
      {
        columnWidth = column.measure.offsetWidth + 'px';
        cssom.setStyleProperty(column.header.firstChild, 'width', columnWidth);
        cssom.setStyleProperty(column.footer.firstChild, 'width', columnWidth);
        //column.header.firstChild.style.width = columnWidth;
        //column.footer.firstChild.style.width = columnWidth;
      }

      //
      // Calc metrics boxes
      //
      var tableWidth = this.tmpl.boundElement.offsetWidth || 0;
      var headerHeight = headerElement.offsetHeight || 0;
      var footerHeight = footerElement.offsetHeight || 0;

      //
      // Update style properties
      //
      this.tmpl.headerExpandCell.style.left = tableWidth + 'px';
      this.tmpl.footerExpandCell.style.left = tableWidth + 'px';
      this.tmpl.tableElement.style.margin = '-' + headerHeight + 'px 0 -' + footerHeight + 'px';
      this.element.style.paddingBottom = (headerHeight + footerHeight) + 'px';

      // reset timer
      // it should be at the end of relayout to prevent relayout call while relayout
      this.timer_ = clearTimeout(this.timer_);
    },

   /**
    * @inheritDoc
    */
    destroy: function(){
      clearTimeout(this.timer_);
      this.timer_ = true; // prevent relayout call

      this.columnWidthSync_ = null;
      this.shadowHeaderHtml_ = null;
      this.shadowFooterHtml_ = null;

      Table.prototype.destroy.call(this);
    }
  });

  //
  // export names
  //

  module.exports = {
    ScrollTable: ScrollTable
  };
<|endoftext|>


<commit_before>/* autogenerated by the update_version script */
exports.version=1574780602;
<commit_msg>bugfix<commit_after>/* autogenerated by the update_version script */
exports.version=1575571338;
<|endoftext|>


<commit_before>/* =============================================================

    Astro v3.1
    Mobile-first navigation patterns by Chris Ferdinandi.
    http://gomakethings.com

    Free to use under the MIT License.
    http://gomakethings.com/mit/

 * ============================================================= */

/* =============================================================
    MICRO-FRAMEWORK
    Simple vanilla JavaScript functions to handle common tasks.
 * ============================================================= */

// Check if an element has a class
var hasClass = function (elem, className) {
    return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
}

// Add a class to an element
var addClass = function (elem, className) {
    if (!hasClass(elem, className)) {
        elem.className += ' ' + className;
    }
}

// Remove a class from an element
var removeClass = function (elem, className) {
    var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ') + ' ';
    if (hasClass(elem, className)) {
        while (newClass.indexOf(' ' + className + ' ') >= 0 ) {
            newClass = newClass.replace(' ' + className + ' ', ' ');
        }
        elem.className = newClass.replace(/^\s+|\s+$/g, '');
    }
}

// Toggle a class on an element
var toggleClass = function (elem, className) {
    if ( hasClass(elem, className) ) {
        removeClass(elem, className);
    }
    else {
        addClass(elem, className);
    }
}

/* =============================================================
    ASTRO FUNCTIONS
    Toggle the navigation menu.
 * ============================================================= */

// Feature Test
if ( 'querySelector' in document && 'addEventListener' in window ) {

    // Function to toggle navigation menu
    var toggleNav = function (toggle) {

        // Get target navigation menu
        var dataID = toggle.getAttribute('data-target');
        var dataTarget = document.querySelector(dataID);

        // Toggle the '.active' class on the menu
        toggleClass(dataTarget, 'active');

    }

    // Define the nav toggle
    var navToggle = document.querySelectorAll('.nav-toggle');

    // For each nav toggle
    [].forEach.call(navToggle, function (toggle) {

        // When nav toggle is clicked
        toggle.addEventListener('click', function(e) {

            // Prevent the default link behavior
            e.preventDefault();

            // Toggle the navigation menu
            toggleNav(toggle);

        }, false);
    });
}
<commit_msg>Updated version number<commit_after>/* =============================================================

    Astro v3.2
    Mobile-first navigation patterns by Chris Ferdinandi.
    http://gomakethings.com

    Free to use under the MIT License.
    http://gomakethings.com/mit/

 * ============================================================= */

/* =============================================================
    MICRO-FRAMEWORK
    Simple vanilla JavaScript functions to handle common tasks.
 * ============================================================= */

// Check if an element has a class
var hasClass = function (elem, className) {
    return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
}

// Add a class to an element
var addClass = function (elem, className) {
    if (!hasClass(elem, className)) {
        elem.className += ' ' + className;
    }
}

// Remove a class from an element
var removeClass = function (elem, className) {
    var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ') + ' ';
    if (hasClass(elem, className)) {
        while (newClass.indexOf(' ' + className + ' ') >= 0 ) {
            newClass = newClass.replace(' ' + className + ' ', ' ');
        }
        elem.className = newClass.replace(/^\s+|\s+$/g, '');
    }
}

// Toggle a class on an element
var toggleClass = function (elem, className) {
    if ( hasClass(elem, className) ) {
        removeClass(elem, className);
    }
    else {
        addClass(elem, className);
    }
}

/* =============================================================
    ASTRO FUNCTIONS
    Toggle the navigation menu.
 * ============================================================= */

// Feature Test
if ( 'querySelector' in document && 'addEventListener' in window ) {

    // Function to toggle navigation menu
    var toggleNav = function (toggle) {

        // Get target navigation menu
        var dataID = toggle.getAttribute('data-target');
        var dataTarget = document.querySelector(dataID);

        // Toggle the '.active' class on the menu
        toggleClass(dataTarget, 'active');

    }

    // Define the nav toggle
    var navToggle = document.querySelectorAll('.nav-toggle');

    // For each nav toggle
    [].forEach.call(navToggle, function (toggle) {

        // When nav toggle is clicked
        toggle.addEventListener('click', function(e) {

            // Prevent the default link behavior
            e.preventDefault();

            // Toggle the navigation menu
            toggleNav(toggle);

        }, false);
    });
}
<|endoftext|>


<commit_before>(function (GOVUK) {
  "use strict";

  var sendVirtualPageView = function() {
    var $element = $(this);
    var url = $element.data('url');
    if (GOVUK.analytics  && url){
      GOVUK.analytics.trackPageview(url);
    }
  };

  GOVUK.GDM.analytics.virtualPageViews = function() {
    var $flashMessage;

    $('[data-analytics=trackPageView]').each(sendVirtualPageView);
    if (GOVUK.GDM.analytics.location.pathname().match(/^\/suppliers\/opportunities\/\d+\/ask-a-question/) !== null) {
      $flashMessage = $('.banner-success-without-action .banner-message');

      if ($flashMessage.text().match(/^Your question has been sent/) !== null) {
        GOVUK.analytics.trackPageview(GOVUK.GDM.analytics.location.href() + '?submitted=true');
      }
    }
  };

})(window.GOVUK);
<commit_msg>Trim whitespace from banner text before checking<commit_after>(function (GOVUK) {
  "use strict";

  var sendVirtualPageView = function() {
    var $element = $(this);
    var url = $element.data('url');
    if (GOVUK.analytics  && url){
      GOVUK.analytics.trackPageview(url);
    }
  };

  GOVUK.GDM.analytics.virtualPageViews = function() {
    var $flashMessage;

    $('[data-analytics=trackPageView]').each(sendVirtualPageView);
    if (GOVUK.GDM.analytics.location.pathname().match(/^\/suppliers\/opportunities\/\d+\/ask-a-question/) !== null) {
      $flashMessage = $('.banner-success-without-action .banner-message');

      if ($flashMessage.text().replace(/^\s+|\s+$/g, '').match(/^Your question has been sent/) !== null) {
        GOVUK.analytics.trackPageview(GOVUK.GDM.analytics.location.href() + '?submitted=true');
      }
    }
  };

})(window.GOVUK);
<|endoftext|>


<commit_before>angular.module('ot.view.branch', [
    'ui.router',
    'ot.service.core',
    'ot.service.form',
    'ot.service.structure',
    'ot.service.buildfilter',
    'ot.dialog.validationStampRunView'
])
    .config(function ($stateProvider) {
        $stateProvider.state('branch', {
            url: '/branch/{branchId}',
            templateUrl: 'app/view/view.branch.tpl.html',
            controller: 'BranchCtrl'
        });
    })
    .controller('BranchCtrl', function ($interval, $state, $scope, $stateParams, $http, $modal, ot, otFormService, otStructureService, otBuildFilterService, otAlertService) {
        var view = ot.view();
        // Branch's id
        var branchId = $stateParams.branchId;

        // Auto refresh status
        function refreshBuildView() {
            loadBuildView();
        }

        $scope.$watch('autoRefresh', function () {
            if ($scope.autoRefresh) {
                $scope.autoRefreshPromise = $interval(refreshBuildView, 30000);
            } else if ($scope.autoRefreshPromise) {
                $interval.cancel($scope.autoRefreshPromise);
            }
        });
        $scope.autoRefresh = localStorage.getItem('autoRefresh');
        $scope.toggleAutoRefresh = function () {
            $scope.autoRefresh = !$scope.autoRefresh;
            localStorage.setItem('autoRefresh', $scope.autoRefresh);
        };

        // Selected builds
        $scope.selectedBuild = {
            from: undefined,
            to: undefined
        };

        // Loading the build filters
        function loadBuildFilters() {
            // Loads filter forms
            ot.call($http.get($scope.branch._buildFilterForms)).then(function (buildFilterForms) {
                $scope.buildFilterForms = buildFilterForms;
                // Loads existing filters
                return otBuildFilterService.loadFilters($scope.branch);
            }).then(function (buildFilterResources) {
                $scope.buildFilterResources = buildFilterResources;
                // Loading the build view AFTER the filter have been loaded
                loadBuildView();
            });
        }

        // Loading the build view
        function loadBuildView() {
            // Parameters for the call
            // TODO Use '_view' link from the branch
            var uri = 'structure/branches/' + branchId + '/view';
            var config = {};
            // Adds the filter parameters
            var currentBuildFilterResource = otBuildFilterService.getCurrentFilter(branchId);
            if (currentBuildFilterResource) {
                $scope.currentBuildFilterResource = currentBuildFilterResource;
                config.params = currentBuildFilterResource.data;
                uri += '/' + currentBuildFilterResource.type;
            } else {
                $scope.currentBuildFilterResource = undefined;
            }
            // Call
            ot.call($http.get(uri, config)).then(
                function success(branchBuildView) {
                    $scope.branchBuildView = branchBuildView;
                    // Selection of build boundaries
                    var buildViews = branchBuildView.buildViews;
                    if (buildViews && buildViews.length > 0) {
                        $scope.selectedBuild.from = buildViews[0].build.id;
                        $scope.selectedBuild.to = buildViews[buildViews.length - 1].build.id;
                    }
                }
            );
        }

        // Loading the promotion levels
        function loadPromotionLevels() {
            ot.call($http.get($scope.branch._promotionLevels)).then(function (collection) {
                $scope.promotionLevelCollection = collection;
                $scope.promotionLevelSortOptions = {
                    disabled: !$scope.branch._reorderPromotionLevels
                };
            });
        }

        // Loading the validation stamps
        function loadValidationStamps() {
            ot.call($http.get($scope.branch._validationStamps)).then(function (collection) {
                $scope.validationStampCollection = collection;
            });
        }

        // Loading the branch
        function loadBranch() {
            otStructureService.getBranch(branchId).then(function (branchResource) {
                $scope.branch = branchResource;
                // View settings
                view.title = branchResource.name;
                view.description = branchResource.description;
                view.breadcrumbs = ot.projectBreadcrumbs(branchResource.project);
                view.decorationsEntity = branchResource;
                // Branch commands
                view.commands = [
                    {
                        condition: function () {
                            return branchResource._createBuild;
                        },
                        id: 'createBuild',
                        name: "Create build",
                        cls: 'ot-command-build-new',
                        action: function () {
                            otStructureService.createBuild(branchResource._createBuild).then(loadBuildView);
                        }
                    },
                    {
                        condition: function () {
                            return branchResource._update;
                        },
                        id: 'updateBranch',
                        name: "Update branch",
                        cls: 'ot-command-branch-update',
                        action: function () {
                            otStructureService.update(
                                branchResource._update,
                                "Update branch"
                            ).then(loadBranch);
                        }
                    },
                    {
                        condition: function () {
                            return $scope.branch._delete;
                        },
                        id: 'deleteBranch',
                        name: "Delete branch",
                        cls: 'ot-command-branch-delete',
                        action: function () {
                            otAlertService.confirm({
                                title: "Deleting a branch",
                                message: "Do you really want to delete the branch " + $scope.branch.name +
                                    " and all its associated data?"
                            }).then(function () {
                                return ot.call($http.delete($scope.branch._delete));
                            }).then(function () {
                                $state.go('project', {projectId: $scope.branch.project.id});
                            });
                        }
                    },
                    ot.viewCloseCommand('/project/' + branchResource.project.id),
                    ot.viewActionsCommand($scope.branch._actions)
                ];
                // Loads the build filters
                loadBuildFilters();
                // Loads the promotion levels
                loadPromotionLevels();
                // Loads the validation stamps
                loadValidationStamps();
            });
        }

        // Initialization
        loadBranch();

        // Creation of a promotion level
        $scope.createPromotionLevel = function () {
            otStructureService.create($scope.branch._createPromotionLevel, "New promotion level").then(loadBranch);
        };

        // Creation of a validation stamp
        $scope.createValidationStamp = function () {
            otStructureService.create($scope.branch._createValidationStamp, 'New validation stamp').then(loadBranch);
        };

        /**
         * Creating a validation run
         */
        $scope.createValidationRun = function (buildView, validationStampRunView) {
            otStructureService.create(
                buildView.build._validate,
                'Validation for the build',
                {
                    postForm: function (form) {
                        return otFormService.updateFieldValue(form, 'validationStamp', validationStampRunView.validationStamp.id);
                    }
                }
            ).then(loadBuildView);
        };

        /**
         * Displaying the validation runs
         */
        $scope.displayValidationRuns = function (buildView, validationStampRunView) {
            $modal.open({
                templateUrl: 'app/dialog/dialog.validationStampRunView.tpl.html',
                controller: 'otDialogValidationStampRunView',
                resolve: {
                    config: function () {
                        return {
                            buildView: buildView,
                            validationStampRunView: validationStampRunView
                        };
                    }
                }
            });
        };

        /**
         * Build diff action
         */
        $scope.buildDiff = function (action) {
            var selectedBuild = $scope.selectedBuild;
            if (selectedBuild.from && selectedBuild.to && selectedBuild.from != selectedBuild.to) {
                $state.go(action.id, {
                    branch: branchId,
                    from: selectedBuild.from,
                    to: selectedBuild.to
                });
            }
        };

        /**
         * Build filter: new one
         */
        $scope.buildFilterNew = function (buildFilterForm) {
            otBuildFilterService.createBuildFilter({
                branchId: branchId,
                buildFilterForm: buildFilterForm
            }).then(function () {
                // Reloads the filters
                loadBuildFilters();
            });
        };

        /**
         * Applying a filter
         */
        $scope.buildFilterApply = function (buildFilterResource) {
            if (!buildFilterResource.removing) {
                otBuildFilterService.storeCurrent(branchId, buildFilterResource);
                loadBuildView();
            }
        };

        /**
         * Removing the current filter
         */
        $scope.buildFilterErase = function () {
            otBuildFilterService.eraseCurrent(branchId);
            loadBuildView();
        };

        /**
         * Removing an existing filter
         */
        $scope.buildFilterRemove = function (buildFilterResource) {
            buildFilterResource.removing = true;
            otBuildFilterService.removeFilter($scope.branch, buildFilterResource).then(loadBuildFilters);
        };

        /**
         * Saving a local filter
         */
        $scope.buildFilterSave = function (buildFilterResource) {
            otBuildFilterService.saveFilter($scope.branch, buildFilterResource).then(loadBuildFilters);
        };

    })
;<commit_msg>Promotion level ordering: sending the reorder request<commit_after>angular.module('ot.view.branch', [
    'ui.router',
    'ot.service.core',
    'ot.service.form',
    'ot.service.structure',
    'ot.service.buildfilter',
    'ot.dialog.validationStampRunView'
])
    .config(function ($stateProvider) {
        $stateProvider.state('branch', {
            url: '/branch/{branchId}',
            templateUrl: 'app/view/view.branch.tpl.html',
            controller: 'BranchCtrl'
        });
    })
    .controller('BranchCtrl', function ($interval, $state, $scope, $stateParams, $http, $modal, ot, otFormService, otStructureService, otBuildFilterService, otAlertService) {
        var view = ot.view();
        // Branch's id
        var branchId = $stateParams.branchId;

        // Auto refresh status
        function refreshBuildView() {
            loadBuildView();
        }

        $scope.$watch('autoRefresh', function () {
            if ($scope.autoRefresh) {
                $scope.autoRefreshPromise = $interval(refreshBuildView, 30000);
            } else if ($scope.autoRefreshPromise) {
                $interval.cancel($scope.autoRefreshPromise);
            }
        });
        $scope.autoRefresh = localStorage.getItem('autoRefresh');
        $scope.toggleAutoRefresh = function () {
            $scope.autoRefresh = !$scope.autoRefresh;
            localStorage.setItem('autoRefresh', $scope.autoRefresh);
        };

        // Selected builds
        $scope.selectedBuild = {
            from: undefined,
            to: undefined
        };

        // Loading the build filters
        function loadBuildFilters() {
            // Loads filter forms
            ot.call($http.get($scope.branch._buildFilterForms)).then(function (buildFilterForms) {
                $scope.buildFilterForms = buildFilterForms;
                // Loads existing filters
                return otBuildFilterService.loadFilters($scope.branch);
            }).then(function (buildFilterResources) {
                $scope.buildFilterResources = buildFilterResources;
                // Loading the build view AFTER the filter have been loaded
                loadBuildView();
            });
        }

        // Loading the build view
        function loadBuildView() {
            // Parameters for the call
            // TODO Use '_view' link from the branch
            var uri = 'structure/branches/' + branchId + '/view';
            var config = {};
            // Adds the filter parameters
            var currentBuildFilterResource = otBuildFilterService.getCurrentFilter(branchId);
            if (currentBuildFilterResource) {
                $scope.currentBuildFilterResource = currentBuildFilterResource;
                config.params = currentBuildFilterResource.data;
                uri += '/' + currentBuildFilterResource.type;
            } else {
                $scope.currentBuildFilterResource = undefined;
            }
            // Call
            ot.call($http.get(uri, config)).then(
                function success(branchBuildView) {
                    $scope.branchBuildView = branchBuildView;
                    // Selection of build boundaries
                    var buildViews = branchBuildView.buildViews;
                    if (buildViews && buildViews.length > 0) {
                        $scope.selectedBuild.from = buildViews[0].build.id;
                        $scope.selectedBuild.to = buildViews[buildViews.length - 1].build.id;
                    }
                }
            );
        }

        // Loading the promotion levels
        function loadPromotionLevels() {
            ot.call($http.get($scope.branch._promotionLevels)).then(function (collection) {
                $scope.promotionLevelCollection = collection;
                $scope.promotionLevelSortOptions = {
                    disabled: !$scope.branch._reorderPromotionLevels,
                    stop: function (event, ui) {
                        var ids = $scope.promotionLevelCollection.resources.map(function (pl) {
                            return pl.id;
                        });
                        ot.call($http.put(
                            $scope.branch._reorderPromotionLevels,
                            { ids: ids}
                        ));
                    }
                };
            });
        }

        // Loading the validation stamps
        function loadValidationStamps() {
            ot.call($http.get($scope.branch._validationStamps)).then(function (collection) {
                $scope.validationStampCollection = collection;
            });
        }

        // Loading the branch
        function loadBranch() {
            otStructureService.getBranch(branchId).then(function (branchResource) {
                $scope.branch = branchResource;
                // View settings
                view.title = branchResource.name;
                view.description = branchResource.description;
                view.breadcrumbs = ot.projectBreadcrumbs(branchResource.project);
                view.decorationsEntity = branchResource;
                // Branch commands
                view.commands = [
                    {
                        condition: function () {
                            return branchResource._createBuild;
                        },
                        id: 'createBuild',
                        name: "Create build",
                        cls: 'ot-command-build-new',
                        action: function () {
                            otStructureService.createBuild(branchResource._createBuild).then(loadBuildView);
                        }
                    },
                    {
                        condition: function () {
                            return branchResource._update;
                        },
                        id: 'updateBranch',
                        name: "Update branch",
                        cls: 'ot-command-branch-update',
                        action: function () {
                            otStructureService.update(
                                branchResource._update,
                                "Update branch"
                            ).then(loadBranch);
                        }
                    },
                    {
                        condition: function () {
                            return $scope.branch._delete;
                        },
                        id: 'deleteBranch',
                        name: "Delete branch",
                        cls: 'ot-command-branch-delete',
                        action: function () {
                            otAlertService.confirm({
                                title: "Deleting a branch",
                                message: "Do you really want to delete the branch " + $scope.branch.name +
                                    " and all its associated data?"
                            }).then(function () {
                                return ot.call($http.delete($scope.branch._delete));
                            }).then(function () {
                                $state.go('project', {projectId: $scope.branch.project.id});
                            });
                        }
                    },
                    ot.viewCloseCommand('/project/' + branchResource.project.id),
                    ot.viewActionsCommand($scope.branch._actions)
                ];
                // Loads the build filters
                loadBuildFilters();
                // Loads the promotion levels
                loadPromotionLevels();
                // Loads the validation stamps
                loadValidationStamps();
            });
        }

        // Initialization
        loadBranch();

        // Creation of a promotion level
        $scope.createPromotionLevel = function () {
            otStructureService.create($scope.branch._createPromotionLevel, "New promotion level").then(loadBranch);
        };

        // Creation of a validation stamp
        $scope.createValidationStamp = function () {
            otStructureService.create($scope.branch._createValidationStamp, 'New validation stamp').then(loadBranch);
        };

        /**
         * Creating a validation run
         */
        $scope.createValidationRun = function (buildView, validationStampRunView) {
            otStructureService.create(
                buildView.build._validate,
                'Validation for the build',
                {
                    postForm: function (form) {
                        return otFormService.updateFieldValue(form, 'validationStamp', validationStampRunView.validationStamp.id);
                    }
                }
            ).then(loadBuildView);
        };

        /**
         * Displaying the validation runs
         */
        $scope.displayValidationRuns = function (buildView, validationStampRunView) {
            $modal.open({
                templateUrl: 'app/dialog/dialog.validationStampRunView.tpl.html',
                controller: 'otDialogValidationStampRunView',
                resolve: {
                    config: function () {
                        return {
                            buildView: buildView,
                            validationStampRunView: validationStampRunView
                        };
                    }
                }
            });
        };

        /**
         * Build diff action
         */
        $scope.buildDiff = function (action) {
            var selectedBuild = $scope.selectedBuild;
            if (selectedBuild.from && selectedBuild.to && selectedBuild.from != selectedBuild.to) {
                $state.go(action.id, {
                    branch: branchId,
                    from: selectedBuild.from,
                    to: selectedBuild.to
                });
            }
        };

        /**
         * Build filter: new one
         */
        $scope.buildFilterNew = function (buildFilterForm) {
            otBuildFilterService.createBuildFilter({
                branchId: branchId,
                buildFilterForm: buildFilterForm
            }).then(function () {
                // Reloads the filters
                loadBuildFilters();
            });
        };

        /**
         * Applying a filter
         */
        $scope.buildFilterApply = function (buildFilterResource) {
            if (!buildFilterResource.removing) {
                otBuildFilterService.storeCurrent(branchId, buildFilterResource);
                loadBuildView();
            }
        };

        /**
         * Removing the current filter
         */
        $scope.buildFilterErase = function () {
            otBuildFilterService.eraseCurrent(branchId);
            loadBuildView();
        };

        /**
         * Removing an existing filter
         */
        $scope.buildFilterRemove = function (buildFilterResource) {
            buildFilterResource.removing = true;
            otBuildFilterService.removeFilter($scope.branch, buildFilterResource).then(loadBuildFilters);
        };

        /**
         * Saving a local filter
         */
        $scope.buildFilterSave = function (buildFilterResource) {
            otBuildFilterService.saveFilter($scope.branch, buildFilterResource).then(loadBuildFilters);
        };

    })
;<|endoftext|>


<commit_before>ModuleLoader.require([
	"tinymce/util/Arr",
	"tinymce/dom/Dimensions"
], function(Arr, Dimensions) {
	module("tinymce.WindowManager", {
		setupModule: function() {
			QUnit.stop();

			tinymce.init({
				selector: "textarea",
				add_unload_trigger: false,
				disable_nodechange: true,
				init_instance_callback: function(ed) {
					window.editor = ed;
					QUnit.start();
				}
			});
		},

		teardown: function() {
			editor.off('CloseWindow OpenWindow');
		}
	});

	test('OpenWindow/CloseWindow events', function() {
		var openWindowArgs, closeWindowArgs;

		editor.on('CloseWindow', function(e) {
			closeWindowArgs = e;
		});

		editor.on('OpenWindow', function(e) {
			openWindowArgs = e;
			e.win.close();
		});

		editor.windowManager.alert('test');

		equal(openWindowArgs.type, 'openwindow');
		equal(closeWindowArgs.type, 'closewindow');
		equal(editor.windowManager.getWindows().length, 0);
	});
});
<commit_msg>Removed unused deps<commit_after>ModuleLoader.require([
], function() {
	module("tinymce.WindowManager", {
		setupModule: function() {
			QUnit.stop();

			tinymce.init({
				selector: "textarea",
				add_unload_trigger: false,
				disable_nodechange: true,
				init_instance_callback: function(ed) {
					window.editor = ed;
					QUnit.start();
				}
			});
		},

		teardown: function() {
			editor.off('CloseWindow OpenWindow');
		}
	});

	test('OpenWindow/CloseWindow events', function() {
		var openWindowArgs, closeWindowArgs;

		editor.on('CloseWindow', function(e) {
			closeWindowArgs = e;
		});

		editor.on('OpenWindow', function(e) {
			openWindowArgs = e;
			e.win.close();
		});

		editor.windowManager.alert('test');

		equal(openWindowArgs.type, 'openwindow');
		equal(closeWindowArgs.type, 'closewindow');
		equal(editor.windowManager.getWindows().length, 0);
	});
});
<|endoftext|>


<commit_before>// 1. create board (6 x 7 square)

// array 0..41
// for loop drops in pre-set sized pieces within container div (inline block)

var boardArray = new Array(42);

function createBoard() {
	var boardContainer = document.createElement('div');
	boardContainer.className = 'boardContainer';
	document.getElementsByClassName('mainContainer')[0].appendChild(boardContainer);

	function square() {
		var boardSquare = document.createElement('div');
		boardSquare.className = 'boardSquare vacant';
		boardSquare.setAttribute('id', counter)
		// boardSquare.innerHTML = counter;
		boardSquare.appendChild(circle());
		return boardSquare;
	}

	function circle() {
		var innerCircle = document.createElement('div');
		innerCircle.className = 'boardCircle';
		innerCircle.setAttribute('id', counter)
		return innerCircle;
	}

	for (var counter = 0; counter < boardArray.length; counter++) {
		boardContainer.appendChild(square());
	};
}

createBoard();

// 2. set 2 players

var player1 = {name: 'Player 1', turn: true, color: 'red'};
var player2 = {name: 'Player 2', turn: false, color: 'black'};

// 3. alternate turns
// turn function assigns a player and after action assigns new player
// action lands piece in specified column (modulus of 7) in last open cell

	var whosTurnIsIt = function() {
		if (player1.turn == true) {
			return player1;
		}
		else {
			return player2;
		}
	}

	var switchPlayer = function() {
		if (player1.turn == true) {
			player1.turn = false;
			player2.turn = true;
		}
		else {
			player1.turn = true;
			player2.turn = false;
		}
	}

// 4. click on col & piece appears
// 0..6 have event listeners: 7 diff click-here areas

	var makeAChecker = function(color) {
		var checker = document.createElement('div');
		checker.className = color;
		checker.className += " checker";
		checker.style.backgroundColor = color;
		return checker;
	}

	var animateChecker = function() {
		var currentPlayer = whosTurnIsIt();
		var column = this.id % 7;
		console.log(column);
		var newChecker = makeAChecker(currentPlayer.color);

		// checker starts in outer space
		// by column, look at last cell and choose the one that is not empty
		// col number + (7*5), loop through 4..1
		// assign tag to announce that slot is occupied
		for (var checkerCounter = 5; checkerCounter > -1; checkerCounter--) {
			var squareId = column + (7 * checkerCounter)
			squareId.toString();
			var vacantCheck = document.getElementById(squareId);
			console.log(vacantCheck)
			if (vacantCheck.className == 'boardSquare vacant') {
				vacantCheck.appendChild(newChecker);
				vacantCheck.className = 'boardSquare occupied';
				switchPlayer();
				break;
			}
		}
	}

	for (var sqCount = 0; sqCount < 42; sqCount++) {
		document.getElementById(sqCount).addEventListener("click", animateChecker, true);
	}

// 5 after each turns

// GARBAGE TIME CHECK: 168 cells touched per turn
// 	5a check row
// splice or slice - for look with counter - when counter == 4: winner
// 	5b check col
//  for loop index i, i + 7, match value, if counter == 4: winner
// 	5c check diag

// MIND-BLOWING ALGORITHM: < 42 cells checked per turn.
// check adjacent cells & brute force against the edges

// destination cell index = x
// check
     // A. +1 & -1
     // 	while x != edge cases
	 // B. +7 & -7
     // 	while x != edge cases
	 // C. +6 & -6
     // 	while x != edge cases
	 // D. +8 & -8
     // 	while x != edge cases

// 6 stop game when there's a winner

<commit_msg>alorithm nightmares<commit_after>// 1. create board (6 x 7 square)

// array 0..41
// for loop drops in pre-set sized pieces within container div (inline block)

var boardArray = new Array(42);
//console.log(boardArray);

function createBoard() {
	var boardContainer = document.createElement('div');
	boardContainer.className = 'boardContainer';
	document.getElementsByClassName('mainContainer')[0].appendChild(boardContainer);

	function square() {
		var boardSquare = document.createElement('div');
		boardSquare.className = 'boardSquare vacant';
		boardSquare.setAttribute('id', counter)
		// boardSquare.innerHTML = counter;
		boardSquare.appendChild(circle());
		return boardSquare;
	}

	function circle() {
		var innerCircle = document.createElement('div');
		innerCircle.className = 'boardCircle';
		innerCircle.setAttribute('id', counter)
		return innerCircle;
	}

	for (var counter = 0; counter < boardArray.length; counter++) {
		boardContainer.appendChild(square());
	};
}

createBoard();

// 2. set 2 players

var player1 = {name: 'Player 1', turn: true, color: 'red', number: 1};
var player2 = {name: 'Player 2', turn: false, color: 'black', number: 2};

// 3. alternate turns
// turn function assigns a player and after action assigns new player
// action lands piece in specified column (modulus of 7) in last open cell

var whosTurnIsIt = function() {
	if (player1.turn == true) {
		return player1;
	}
	else {
		return player2;
	}
}

var switchPlayer = function() {
	if (player1.turn == true) {
		player1.turn = false;
		player2.turn = true;
	}
	else {
		player1.turn = true;
		player2.turn = false;
	}
}

// 4. click on col & piece appears
// 0..6 have event listeners: 7 diff click-here areas

var makeAChecker = function(color) {
	var checker = document.createElement('div');
	checker.className = color;
	checker.className += " checker";
	checker.style.backgroundColor = color;
	return checker;
}

var animateChecker = function() {
	var currentPlayer = whosTurnIsIt();
	var column = this.id % 7;
	//console.log(column);
	var newChecker = makeAChecker(currentPlayer.color);

		// checker starts in outer space
		// by column, look at last cell and choose the one that is not empty
		// col number + (7*5), loop through 4..1
		// assign tag to announce that slot is occupied
		for (var checkerCounter = 5; checkerCounter > -1; checkerCounter--) {
			var squareId = column + (7 * checkerCounter)
			squareId.toString();
			var vacantCheck = document.getElementById(squareId);
			console.log(vacantCheck)
			if (vacantCheck.className == 'boardSquare vacant') {
				vacantCheck.appendChild(newChecker);
				vacantCheck.className = 'boardSquare occupied';
				boardArray[squareId] = currentPlayer.number;
				checkForWinner(squareId);
				switchPlayer();
				break;
			}
		}
	}

	for (var sqCount = 0; sqCount < 42; sqCount++) {
		document.getElementById(sqCount).addEventListener("click", animateChecker, true);
	}

// 5. after each turns

// GARBAGE TIME CHECK: 168 cells touched per turn
// 	5a check row
// splice or slice - for look with counter - when counter == 4: winner
// 	5b check col
//  for loop index i, i + 7, match value, if counter == 4: winner
// 	5c check diag

// MIND-BLOWING ALGORITHM: < 42 cells checked per turn.
// check adjacent cells & brute force against the edges

function checkForWinner(index) {

	// destination cell index = x
	// check
     // A. +1 & -1
     // 	while x != edge cases
	 // B. +7 & -7
     // 	while x != edge cases
	 // C. +6 & -6
     // 	while x != edge cases
	 // D. +8 & -8
     // 	while x != edge cases

 	var countingToFour = 1
    var testCases = [1, 6, 7, 8];

    // loop to check all 8 surrounding cell squares for a matching value (-/+ 1, 6, 7 or 8 indices away)
	for (var counter0 = 0; counter0 < testCases.length; counter0++) {

		    console.log("num in cell: ");
     		console.log(boardArray[index]);

		// if the player # (just-placed checker) in the array matches the value in the contiguous cell
		// run the next loop
     	if (boardArray[index] === boardArray[index - testCases[counter0]] || boardArray[index] === boardArray[index+testCases[counter0]]) {

     		// when a match is found, check the next cell in that direction (-/+)
     		for(var i = index; boardArray[i] === boardArray[i-testCases[counter0]]; i-=testCases[counter0]) {
     			countingToFour++;
     			//console.log("loop2");
     			if (countingToFour === 4) {
     				console.log("winner1")
     				return "Winner";
     			}

     		}
     		// when a match is found, check the next cell in the other direction (-/+)
     		for (var j = index; boardArray[j] === boardArray[j+testCases[counter0]]; i+=testCases[counter0]) {
     			//console.log("loop3");
     			console.log(countingToFour)
     			countingToFour++;
     			if (countingToFour === 4) {
     				console.log("winner2")
     				return "Winner";
     			}

     		}
		//console.log(countingToFour);
		countingToFour = 1;
		}
	}
}

// 6 stop game when there's a winner

<|endoftext|>