<commit_before>import d3 from 'd3';
import { isArray, isPlainObject, isEmpty } from 'lodash/lang';
import mapValues from 'lodash/object/mapValues';
import map2tree from 'map2tree';
import { getTooltipString, toggleChildren, visit, getNodeGroupByDepthCount } from './utils';
import d3tooltip from 'd3-tooltip';

export default function(DOMNode, props) {
  const {
    id = 'd3svg',
    style = '',
    size = 1000,
    aspectRatio = 1.0,
    isSorted = false,
    widthBetweenBranchCoeff = 1,
    heightBetweenNodesCoeff = 1,
    transitionDuration = 750,
    tooltipOptions = {
      left: undefined,
      right: undefined,
      offset: {
        left: 0,
        top: 0
      }
    }
    } = props;
  const margin = {
    top: size / 100,
    right: size / 50,
    bottom: size / 100,
    left: 40
  };
  const width = size - margin.left - margin.right;
  const height = size * aspectRatio - margin.top - margin.bottom;
  const fullWidth = size;
  const fullHeight = size * aspectRatio;

  const root = d3.select(DOMNode);
  const vis = root
    .append('svg')
    .attr({
      id,
      style,
      width: fullWidth,
      viewBox: `0 0 ${fullWidth} ${fullHeight}`,
      preserveAspectRatio: 'xMinYMin slice'
    })
    .append('g')
    .attr({
      transform: `translate(${margin.left}, ${margin.top})`
    });

  let tree = d3.layout.tree().size([width, height]);
  let data;

  if (isSorted) {
    tree.sort((a, b) => b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1);
  }

  return function renderChart(nextState = props.state || props.tree) {
    data = !props.tree ? map2tree(nextState, 'state') : nextState;

    if (isEmpty(data) || !data.name) {
      throw new Error('Cannot render tree chart: empty data.');
    }

    let nodeIndex = 0;
    let maxLabelLength = 0;

    visit(data,
        node => maxLabelLength = Math.max(node.name.length, maxLabelLength),
        node => node.children && node.children.length > 0 ? node.children : null
    );

    data.x0 = height / 2;
    data.y0 = 0;
    /*eslint-disable*/
    update(data);
    /*eslint-enable*/

    function update(source) {
      // path generator for links
      const diagonal = d3.svg.diagonal().projection(d => [d.y, d.x]);
      // set tree dimensions and spacing between branches and nodes
      const maxNodeCountByLevel = Math.max(...getNodeGroupByDepthCount(data));

      tree = tree.size([maxNodeCountByLevel * 25 * widthBetweenBranchCoeff, width]);

      let nodes = tree.nodes(data);
      let links = tree.links(nodes);

      nodes.forEach(node => node.y = node.depth * (maxLabelLength * 7 * heightBetweenNodesCoeff));

      // process the node selection
      let node = vis.selectAll('g.node').data(nodes, d => d.id || (d.id = ++nodeIndex));

      let nodeEnter = node.enter().append('g')
        .attr({
          'class': 'node',
          transform: d => `translate(${source.y0},${source.x0})`
        })
        .call(d3tooltip(d3, 'tooltip', tooltipOptions)
          .text((node, i) => getTooltipString(node, i, tooltipOptions)))
        .on({
          click: clickedNode => {
            if (d3.event.defaultPrevented) return;
            update(toggleChildren(clickedNode));
          },
          mouseover: function mouseover(node, i) {
            d3.select(this).style({
              fill: 'skyblue'
            });
          },
          mouseout: function mouseout(node, i) {
            d3.select(this).style({
              fill: 'black'
            });
          }
        });

      nodeEnter.append('circle')
        .attr({
          'class': 'nodeCircle'
        });

      nodeEnter.append('text')
        .attr({
          'class': 'nodeText',
          dy: '.35em'
        })
        .style({
          'fill-opacity': 0
        })
        .text(d => d.name);

      // update the text to reflect whether node has children or not
      node.select('text')
        .attr({
          x: d => d.children || d._children ? -10 : 10,
          'text-anchor': d => d.children || d._children ? 'end' : 'start'
        })
        .text(d => d.name);

      // change the circle fill depending on whether it has children and is collapsed
      node.select('circle.nodeCircle')
        .attr({
          r: 4.5
        })
        .style({
          fill: d => d._children ? 'lightsteelblue' : (d.children ? '#fff' : '#ccc')
        });

      // transition nodes to their new position
      let nodeUpdate = node.transition()
        .duration(transitionDuration)
        .attr({
          transform: d => `translate(${d.y},${d.x})`
        });

      // fade the text in
      nodeUpdate.select('text')
        .style('fill-opacity', 1);

      // transition exiting nodes to the parent's new position
      let nodeExit = node.exit().transition()
        .duration(transitionDuration)
        .attr({
          transform: d => `translate(${source.y},${source.x})`
        })
        .remove();

      nodeExit.select('circle')
        .attr('r', 0);

      nodeExit.select('text')
        .style('fill-opacity', 0);

      // update the links
      let link = vis.selectAll('path.link')
        .data(links, d => d.target.id);

      // enter any new links at the parent's previous position
      link.enter().insert('path', 'g')
        .attr({
          'class': 'link',
          d: d => {
            let o = {
              x: source.x0,
              y: source.y0
            };
            return diagonal({
              source: o,
              target: o
            });
          }
        });

      // transition links to their new position
      link.transition()
        .duration(transitionDuration)
        .attr({
          d: diagonal
        });

      // transition exiting nodes to the parent's new position
      link.exit().transition()
        .duration(transitionDuration)
        .attr({
          d: d => {
            let o = {
              x: source.x,
              y: source.y
            };
            return diagonal({
              source: o,
              target: o
            });
          }
        })
        .remove();

      // stash the old positions for transition
      nodes.forEach(d => {
        d.x0 = d.x;
        d.y0 = d.y;
      });
    }
  };
}
<commit_msg>Allow user to override svg width attribute with style Add rootNameKey option Pass root selection to tooltip Better default parameters handling<commit_after>import d3 from 'd3';
import { isArray, isPlainObject, isEmpty } from 'lodash/lang';
import mapValues from 'lodash/object/mapValues';
import map2tree from 'map2tree';
import { getTooltipString, toggleChildren, visit, getNodeGroupByDepthCount } from './utils';
import d3tooltip from 'd3-tooltip';

const defaultOptions = {
  id: 'd3svg',
  style: {},
  size: 500,
  aspectRatio: 1.0,
  isSorted: false,
  widthBetweenBranchCoeff: 1,
  heightBetweenNodesCoeff: 1,
  transitionDuration: 750,
  state: {error: 'Please provide a state map or a tree structure'},
  rootKeyName: 'state',
  tooltipOptions: {
    left: undefined,
    right: undefined,
    offset: {
      left: 0,
      top: 0
    }
  }
};

export default function(DOMNode, options = {}) {

  const {
    id,
    style,
    size,
    aspectRatio,
    isSorted,
    widthBetweenBranchCoeff,
    heightBetweenNodesCoeff,
    transitionDuration,
    state,
    rootKeyName,
    tree,
    tooltipOptions
    } = {...defaultOptions, ...options};

  const margin = {
    top: size / 100,
    right: size / 50,
    bottom: size / 100,
    left: 40
  };
  const width = size - margin.left - margin.right;
  const height = size * aspectRatio - margin.top - margin.bottom;
  const fullWidth = size;
  const fullHeight = size * aspectRatio;

  const attr = {
    id,
    viewBox: `0 0 ${fullWidth} ${fullHeight}`,
    preserveAspectRatio: 'xMinYMin slice'
  };

  if (!style.width) {
    attr.width = fullWidth;
  }

  const root = d3.select(DOMNode);
  const vis = root
    .append('svg')
    .attr(attr)
    .style(style)
    .append('g')
    .attr({
      transform: `translate(${margin.left}, ${margin.top})`
    });

  let layout = d3.layout.tree().size([width, height]);
  let data;

  if (isSorted) {
    layout.sort((a, b) => b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1);
  }

  return function renderChart(nextState = state || tree) {
    data = !tree ? map2tree(nextState, {key: rootKeyName}) : nextState;

    if (isEmpty(data) || !data.name) {
      throw new Error('Cannot render tree chart: empty data.');
    }

    let nodeIndex = 0;
    let maxLabelLength = 0;

    visit(data,
        node => maxLabelLength = Math.max(node.name.length, maxLabelLength),
        node => node.children && node.children.length > 0 ? node.children : null
    );

    data.x0 = height / 2;
    data.y0 = 0;
    /*eslint-disable*/
    update(data);
    /*eslint-enable*/

    function update(source) {
      // path generator for links
      const diagonal = d3.svg.diagonal().projection(d => [d.y, d.x]);
      // set tree dimensions and spacing between branches and nodes
      const maxNodeCountByLevel = Math.max(...getNodeGroupByDepthCount(data));

      layout = layout.size([maxNodeCountByLevel * 25 * widthBetweenBranchCoeff, width]);

      let nodes = layout.nodes(data);
      let links = layout.links(nodes);

      nodes.forEach(node => node.y = node.depth * (maxLabelLength * 7 * heightBetweenNodesCoeff));

      // process the node selection
      let node = vis.selectAll('g.node').data(nodes, d => d.id || (d.id = ++nodeIndex));

      let nodeEnter = node.enter().append('g')
        .attr({
          'class': 'node',
          transform: d => `translate(${source.y0},${source.x0})`
        })
        .call(d3tooltip(d3, 'tooltip', {...tooltipOptions, root})
          .text((node, i) => getTooltipString(node, i, tooltipOptions)))
        .on({
          click: clickedNode => {
            if (d3.event.defaultPrevented) return;
            update(toggleChildren(clickedNode));
          },
          mouseover: function mouseover(node, i) {
            d3.select(this).style({
              fill: 'skyblue'
            });
          },
          mouseout: function mouseout(node, i) {
            d3.select(this).style({
              fill: 'black'
            });
          }
        });

      nodeEnter.append('circle')
        .attr({
          'class': 'nodeCircle'
        });

      nodeEnter.append('text')
        .attr({
          'class': 'nodeText',
          dy: '.35em'
        })
        .style({
          'fill-opacity': 0
        })
        .text(d => d.name);

      // update the text to reflect whether node has children or not
      node.select('text')
        .attr({
          x: d => d.children || d._children ? -10 : 10,
          'text-anchor': d => d.children || d._children ? 'end' : 'start'
        })
        .text(d => d.name);

      // change the circle fill depending on whether it has children and is collapsed
      node.select('circle.nodeCircle')
        .attr({
          r: 4.5
        })
        .style({
          fill: d => d._children ? 'lightsteelblue' : (d.children ? '#fff' : '#ccc')
        });

      // transition nodes to their new position
      let nodeUpdate = node.transition()
        .duration(transitionDuration)
        .attr({
          transform: d => `translate(${d.y},${d.x})`
        });

      // fade the text in
      nodeUpdate.select('text')
        .style('fill-opacity', 1);

      // transition exiting nodes to the parent's new position
      let nodeExit = node.exit().transition()
        .duration(transitionDuration)
        .attr({
          transform: d => `translate(${source.y},${source.x})`
        })
        .remove();

      nodeExit.select('circle')
        .attr('r', 0);

      nodeExit.select('text')
        .style('fill-opacity', 0);

      // update the links
      let link = vis.selectAll('path.link')
        .data(links, d => d.target.id);

      // enter any new links at the parent's previous position
      link.enter().insert('path', 'g')
        .attr({
          'class': 'link',
          d: d => {
            let o = {
              x: source.x0,
              y: source.y0
            };
            return diagonal({
              source: o,
              target: o
            });
          }
        });

      // transition links to their new position
      link.transition()
        .duration(transitionDuration)
        .attr({
          d: diagonal
        });

      // transition exiting nodes to the parent's new position
      link.exit().transition()
        .duration(transitionDuration)
        .attr({
          d: d => {
            let o = {
              x: source.x,
              y: source.y
            };
            return diagonal({
              source: o,
              target: o
            });
          }
        })
        .remove();

      // stash the old positions for transition
      nodes.forEach(d => {
        d.x0 = d.x;
        d.y0 = d.y;
      });
    }
  };
}
<|endoftext|>


<commit_before>module.exports = function() {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'formio-wizard.html',
    scope: {
      src: '=?',
      url: '=?',
      formAction: '=?',
      form: '=?',
      submission: '=?',
      readOnly: '=?',
      hideComponents: '=?',
      disableComponents: '=?',
      formioOptions: '=?',
      storage: '=?'
    },
    link: function(scope, element) {
      // From https://siongui.github.io/2013/05/12/angularjs-get-element-offset-position/
      var offset = function(elm) {
        try {
          return elm.offset();
        }
        catch (e) {
          // Do nothing...
        }
        var rawDom = elm[0];
        var _x = 0;
        var _y = 0;
        var body = document.documentElement || document.body;
        var scrollX = window.pageXOffset || body.scrollLeft;
        var scrollY = window.pageYOffset || body.scrollTop;
        _x = rawDom.getBoundingClientRect().left + scrollX;
        _y = rawDom.getBoundingClientRect().top + scrollY;
        return {
          left: _x,
          top: _y
        };
      };

      scope.wizardLoaded = false;
      scope.wizardTop = offset(element).top;
      if (scope.wizardTop > 50) {
        scope.wizardTop -= 50;
      }
      scope.wizardElement = angular.element('.formio-wizard', element);
    },
    controller: [
      '$scope',
      '$compile',
      '$element',
      'Formio',
      'FormioScope',
      'FormioUtils',
      '$http',
      '$timeout',
      function(
        $scope,
        $compile,
        $element,
        Formio,
        FormioScope,
        FormioUtils,
        $http,
        $timeout
      ) {
        var session = ($scope.storage && !$scope.readOnly) ? localStorage.getItem($scope.storage) : false;
        if (session) {
          session = angular.fromJson(session);
        }

        $scope.formio = null;
        $scope.url = $scope.url || $scope.src;
        $scope.page = {};
        $scope.pages = [];
        $scope.hasTitles = false;
        $scope.colclass = '';
        if (!$scope.submission || !Object.keys($scope.submission).length) {
          $scope.submission = session ? {data: session.data} : {data: {}};
        }
        $scope.currentPage = session ? session.page : 0;
        $scope.formioAlerts = [];
        $scope.formioOptions = $scope.formioOptions || {};

        var getForm = function() {
          var element = $element.find('#formio-wizard-form');
          if (!element.length) {
            return {};
          }
          return element.children().scope().formioForm;
        };

        // Show the current page.
        var showPage = function(scroll) {
          // When allowing navigate on invsalid
          // prev page alert can be visible.
          // Let's clear it
          $scope.showAlerts(null);
          $scope.pageWasVisited[$scope.currentPage] = true;

          $scope.wizardLoaded = false;
          $scope.page.components = [];
          $scope.page.components.length = 0;
          $timeout(function() {
            // If the page is past the components length, try to clear first.
            if ($scope.currentPage >= $scope.pages.length) {
              $scope.clear();
            }

            if ($scope.storage && !$scope.readOnly) {
              localStorage.setItem($scope.storage, angular.toJson({
                page: $scope.currentPage,
                data: $scope.submission.data
              }));
            }

            $scope.page.components = $scope.pages[$scope.currentPage].components;
            $scope.formioAlerts = [];
            if (scroll) {
              window.scrollTo(0, $scope.wizardTop);
            }
            $scope.wizardLoaded = true;
            $scope.$emit('wizardPage', $scope.currentPage);
            $timeout($scope.$apply.bind($scope));
          });
        };

        if (!$scope.form && $scope.src) {
          (new Formio($scope.src)).loadForm().then(function(form) {
            $scope.form = form;
            if (!$scope.wizardLoaded) {
              showPage();
            }
          });
        }

        // We can be comming back with the 'prev' button.
        // Wait for the form to be loaded.
        // Then timeout to wait the loaded form to be rendered
        // before checking for errors.
        $scope.$on('formLoad', function() {
          if ($scope.pageHasErrors[$scope.currentPage]) {
            $timeout(function() {
              $scope.checkErrors();
            });
          }
        });

        // Shows the given alerts (single or array), and dismisses old alerts
        this.showAlerts = $scope.showAlerts = function(alerts) {
          $scope.formioAlerts = [].concat(alerts);
        };

        $scope.clear = function() {
          if ($scope.storage && !$scope.readOnly) {
            localStorage.setItem($scope.storage, '');
          }
          $scope.submission = {data: {}};
          $scope.currentPage = 0;
        };

        // Check for errors.
        $scope.checkErrors = function() {
          if (!$scope.isValid()) {
            // Change all of the fields to not be pristine.
            angular.forEach($element.find('[name="formioForm"]').children(), function(element) {
              var elementScope = angular.element(element).scope();
              var fieldForm = elementScope.formioForm;
              if (fieldForm[elementScope.component.key]) {
                fieldForm[elementScope.component.key].$pristine = false;
              }
            });
            $scope.formioAlerts = [{
              type: 'danger',
              message: 'Please fix the following errors before proceeding.'
            }];
            return true;
          }
          return false;
        };

        // Submit the submission.
        $scope.submit = function() {
          if ($scope.checkErrors()) {
            return;
          }

          // We want to submit, but free navigation is enabled.
          // Lets check if previous pages where not visited or has errors.
          // If find one, stop searching, go to that page and do not continue with the submission.
          if ($scope.formioOptions.wizardFreeNavigation) {
            var backToPage = null;
            for (var i = 0; i < $scope.pages.length; i++) {
              if ($scope.pageHasErrors[i] || !$scope.pageWasVisited[i]) {
                backToPage = i;
                break;
              }
            }
            if (backToPage !== null) {
              return $scope.goto(backToPage);
            }
          }

          // Create a sanitized submission object.
          var submissionData = {data: {}};
          if ($scope.submission._id) {
            submissionData._id = $scope.submission._id;
          }
          if ($scope.submission.data._id) {
            submissionData._id = $scope.submission.data._id;
          }

          var grabIds = function(input) {
            if (!input) {
              return [];
            }

            if (!(input instanceof Array)) {
              input = [input];
            }

            var final = [];
            input.forEach(function(element) {
              if (element && element._id) {
                final.push(element._id);
              }
            });

            return final;
          };

          var defaultPermissions = {};
          FormioUtils.eachComponent($scope.form.components, function(component) {
            if (component.type === 'resource' && component.key && component.defaultPermission) {
              defaultPermissions[component.key] = component.defaultPermission;
            }
            if (submissionData.data.hasOwnProperty(component.key) && (component.type === 'number')) {
              var value = $scope.submission.data[component.key];
              if (component.type === 'number') {
                submissionData.data[component.key] = value ? parseFloat(value) : 0;
              }
              else {
                submissionData.data[component.key] = value;
              }
            }
          }, true);

          angular.forEach($scope.submission.data, function(value, key) {
            submissionData.data[key] = value;

            // Setup the submission access.
            var perm = defaultPermissions[key];
            if (perm) {
              submissionData.access = submissionData.access || [];

              // Coerce value into an array for plucking.
              if (!(value instanceof Array)) {
                value = [value];
              }

              // Try to find and update an existing permission.
              var found = false;
              submissionData.access.forEach(function(permission) {
                if (permission.type === perm) {
                  found = true;
                  permission.resources = permission.resources || [];
                  permission.resources.concat(grabIds(value));
                }
              });

              // Add a permission, because one was not found.
              if (!found) {
                submissionData.access.push({
                  type: perm,
                  resources: grabIds(value)
                });
              }
            }
          });
          // Strip out any angular keys.
          submissionData = angular.copy(submissionData);

          var submitEvent = $scope.$emit('formSubmit', submissionData);
          if (submitEvent.defaultPrevented) {
              // Listener wants to cancel the form submission
              return;
          }

          var onDone = function(submission) {
            if ($scope.storage && !$scope.readOnly) {
              localStorage.setItem($scope.storage, '');
            }
            $scope.showAlerts({
              type: 'success',
              message: 'Submission Complete!'
            });
            $scope.$emit('formSubmission', submission);
          };

          // Save to specified action.
          if ($scope.action) {
            var method = submissionData._id ? 'put' : 'post';
            $http[method]($scope.action, submissionData).then(function(submission) {
              Formio.clearCache();
              onDone(submission);
            }, FormioScope.onError($scope, $element));
          }
          else if ($scope.formio && !$scope.formio.noSubmit) {
            $scope.formio.saveSubmission(submissionData).then(onDone).catch(FormioScope.onError($scope, $element));
          }
          else {
            onDone(submissionData);
          }
        };

        $scope.cancel = function() {
          $scope.clear();
          showPage(true);
          $scope.$emit('cancel');
        };

        $scope.pageHasErrors = {};
        $scope.pageWasVisited = {};

        // Move onto the next page.
        $scope.next = function() {
          var errors = $scope.checkErrors();
          if (errors) {
            $scope.pageHasErrors[$scope.currentPage] = true;
            if (!$scope.formioOptions.wizardFreeNavigation) {
              return;
            }
          }
          else {
            $scope.pageHasErrors[$scope.currentPage] = false;
          }
          if ($scope.currentPage >= ($scope.pages.length - 1)) {
            return;
          }
          $scope.currentPage++;
          showPage(true);
          $scope.$emit('wizardNext', $scope.currentPage);
        };

        // Move onto the previous page.
        $scope.prev = function() {
          if ($scope.currentPage < 1) {
            return;
          }
          $scope.currentPage--;
          showPage(true);
          $scope.$emit('wizardPrev', $scope.currentPage);
        };

        $scope.goto = function(page) {
          if (page < 0) {
            return;
          }
          if (page >= $scope.pages.length) {
            return;
          }
          var errors = $scope.checkErrors();
          $scope.pageHasErrors[$scope.currentPage] = errors;
          $scope.currentPage = page;
          showPage(true);
        };

        $scope.isValid = function() {
          return getForm().$valid;
        };

        $scope.$on('wizardGoToPage', function(event, page) {
          $scope.goto(page);
        });

        var updatePages = function() {
          if ($scope.pages.length > 6) {
            $scope.margin = ((1 - ($scope.pages.length * 0.0833333333)) / 2) * 100;
            $scope.colclass = 'col-sm-1';
          }
          else {
            $scope.margin = ((1 - ($scope.pages.length * 0.1666666667)) / 2) * 100;
            $scope.colclass = 'col-sm-2';
          }
        };

        var allPages = [];
        var hasConditionalPages = false;
        var setForm = function(form) {
          $scope.pages = [];
          angular.forEach(form.components, function(component) {
            // Only include panels for the pages.
            if (component.type === 'panel') {
              if (!$scope.hasTitles && component.title) {
                $scope.hasTitles = true;
              }
              if (component.customConditional) {
                hasConditionalPages = true;
              }
              else if (component.conditional && component.conditional.when) {
                hasConditionalPages = true;
              }
              // Make sure this page is not in the hide compoenents array.
              if (
                ($scope.hideComponents) &&
                (component.key) &&
                ($scope.hideComponents.indexOf(component.key) !== -1)
              ) {
                return;
              }
              allPages.push(component);
              $scope.pages.push(component);
            }
          });

          // FOR-71
          if (!$scope.builder && hasConditionalPages) {
            $scope.$watch('submission.data', function(data) {
              var newPages = [];
              angular.forEach(allPages, function(page) {
                if (FormioUtils.isVisible(page, null, data)) {
                  newPages.push(page);
                }
              });
              $scope.pages = newPages;
              updatePages();
              setTimeout($scope.$apply.bind($scope), 10);
            }, true);
          }

          $scope.form = $scope.form ? angular.merge($scope.form, angular.copy(form)) : angular.copy(form);
          $scope.page = angular.copy(form);
          $scope.page.display = 'form';
          $scope.$emit('wizardFormLoad', form);
          updatePages();
          showPage();
        };

        // FOR-71
        if (!$scope.builder) {
          $scope.$watch('form', function(form) {
            if (
              $scope.src ||
              !form ||
              !Object.keys(form).length ||
              !form.components ||
              !form.components.length
            ) {
              return;
            }
            var formUrl = form.project ? '/project/' + form.project : '';
            formUrl += '/form/' + form._id;
            $scope.formio = new Formio(formUrl);
            setForm(form);
          });
        }

        // When the components length changes update the pages.
        $scope.$watch('form.components.length', updatePages);

        // Load the form.
        if ($scope.src) {
          $scope.formio = new Formio($scope.src);
          $scope.formio.loadForm().then(function(form) {
            setForm(form);
          });
        }
        else {
          $scope.src = '';
          $scope.formio = new Formio($scope.src);
        }
      }
    ]
  };
};
<commit_msg>Fixed issue with the fields not validating in a wizard.<commit_after>module.exports = function() {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'formio-wizard.html',
    scope: {
      src: '=?',
      url: '=?',
      formAction: '=?',
      form: '=?',
      submission: '=?',
      readOnly: '=?',
      hideComponents: '=?',
      disableComponents: '=?',
      formioOptions: '=?',
      storage: '=?'
    },
    link: function(scope, element) {
      // From https://siongui.github.io/2013/05/12/angularjs-get-element-offset-position/
      var offset = function(elm) {
        try {
          return elm.offset();
        }
        catch (e) {
          // Do nothing...
        }
        var rawDom = elm[0];
        var _x = 0;
        var _y = 0;
        var body = document.documentElement || document.body;
        var scrollX = window.pageXOffset || body.scrollLeft;
        var scrollY = window.pageYOffset || body.scrollTop;
        _x = rawDom.getBoundingClientRect().left + scrollX;
        _y = rawDom.getBoundingClientRect().top + scrollY;
        return {
          left: _x,
          top: _y
        };
      };

      scope.wizardLoaded = false;
      scope.wizardTop = offset(element).top;
      if (scope.wizardTop > 50) {
        scope.wizardTop -= 50;
      }
      scope.wizardElement = angular.element('.formio-wizard', element);
    },
    controller: [
      '$scope',
      '$compile',
      '$element',
      'Formio',
      'FormioScope',
      'FormioUtils',
      '$http',
      '$timeout',
      function(
        $scope,
        $compile,
        $element,
        Formio,
        FormioScope,
        FormioUtils,
        $http,
        $timeout
      ) {
        var session = ($scope.storage && !$scope.readOnly) ? localStorage.getItem($scope.storage) : false;
        if (session) {
          session = angular.fromJson(session);
        }

        $scope.formio = null;
        $scope.url = $scope.url || $scope.src;
        $scope.page = {};
        $scope.pages = [];
        $scope.hasTitles = false;
        $scope.colclass = '';
        if (!$scope.submission || !Object.keys($scope.submission).length) {
          $scope.submission = session ? {data: session.data} : {data: {}};
        }
        $scope.currentPage = session ? session.page : 0;
        $scope.formioAlerts = [];
        $scope.formioOptions = $scope.formioOptions || {};

        var getForm = function() {
          var element = $element.find('#formio-wizard-form');
          if (!element.length) {
            return {};
          }
          return element.children().scope().formioForm;
        };

        // Show the current page.
        var showPage = function(scroll) {
          // When allowing navigate on invsalid
          // prev page alert can be visible.
          // Let's clear it
          $scope.showAlerts(null);
          $scope.pageWasVisited[$scope.currentPage] = true;

          $scope.wizardLoaded = false;
          $scope.page.components = [];
          $scope.page.components.length = 0;
          $timeout(function() {
            // If the page is past the components length, try to clear first.
            if ($scope.currentPage >= $scope.pages.length) {
              $scope.clear();
            }

            if ($scope.storage && !$scope.readOnly) {
              localStorage.setItem($scope.storage, angular.toJson({
                page: $scope.currentPage,
                data: $scope.submission.data
              }));
            }

            $scope.page.components = $scope.pages[$scope.currentPage].components;
            $scope.formioAlerts = [];
            if (scroll) {
              window.scrollTo(0, $scope.wizardTop);
            }
            $scope.wizardLoaded = true;
            $scope.$emit('wizardPage', $scope.currentPage);
            $timeout($scope.$apply.bind($scope));
          });
        };

        if (!$scope.form && $scope.src) {
          (new Formio($scope.src)).loadForm().then(function(form) {
            $scope.form = form;
            if (!$scope.wizardLoaded) {
              showPage();
            }
          });
        }

        // We can be comming back with the 'prev' button.
        // Wait for the form to be loaded.
        // Then timeout to wait the loaded form to be rendered
        // before checking for errors.
        $scope.$on('formLoad', function() {
          if ($scope.pageHasErrors[$scope.currentPage]) {
            $timeout(function() {
              $scope.checkErrors();
            });
          }
        });

        // Shows the given alerts (single or array), and dismisses old alerts
        this.showAlerts = $scope.showAlerts = function(alerts) {
          $scope.formioAlerts = [].concat(alerts);
        };

        $scope.clear = function() {
          if ($scope.storage && !$scope.readOnly) {
            localStorage.setItem($scope.storage, '');
          }
          $scope.submission = {data: {}};
          $scope.currentPage = 0;
        };

        // Check for errors.
        $scope.checkErrors = function() {
          if (!$scope.isValid()) {
            // Change all of the fields to not be pristine.
            angular.forEach($element.find('[name="formioForm"]').find('*'), function(element) {
              var elementScope = angular.element(element).scope();
              var fieldForm = elementScope.formioForm;
              if (fieldForm[elementScope.component.key]) {
                fieldForm[elementScope.component.key].$pristine = false;
              }
            });
            $scope.formioAlerts = [{
              type: 'danger',
              message: 'Please fix the following errors before proceeding.'
            }];
            return true;
          }
          return false;
        };

        // Submit the submission.
        $scope.submit = function() {
          if ($scope.checkErrors()) {
            return;
          }

          // We want to submit, but free navigation is enabled.
          // Lets check if previous pages where not visited or has errors.
          // If find one, stop searching, go to that page and do not continue with the submission.
          if ($scope.formioOptions.wizardFreeNavigation) {
            var backToPage = null;
            for (var i = 0; i < $scope.pages.length; i++) {
              if ($scope.pageHasErrors[i] || !$scope.pageWasVisited[i]) {
                backToPage = i;
                break;
              }
            }
            if (backToPage !== null) {
              return $scope.goto(backToPage);
            }
          }

          // Create a sanitized submission object.
          var submissionData = {data: {}};
          if ($scope.submission._id) {
            submissionData._id = $scope.submission._id;
          }
          if ($scope.submission.data._id) {
            submissionData._id = $scope.submission.data._id;
          }

          var grabIds = function(input) {
            if (!input) {
              return [];
            }

            if (!(input instanceof Array)) {
              input = [input];
            }

            var final = [];
            input.forEach(function(element) {
              if (element && element._id) {
                final.push(element._id);
              }
            });

            return final;
          };

          var defaultPermissions = {};
          FormioUtils.eachComponent($scope.form.components, function(component) {
            if (component.type === 'resource' && component.key && component.defaultPermission) {
              defaultPermissions[component.key] = component.defaultPermission;
            }
            if (submissionData.data.hasOwnProperty(component.key) && (component.type === 'number')) {
              var value = $scope.submission.data[component.key];
              if (component.type === 'number') {
                submissionData.data[component.key] = value ? parseFloat(value) : 0;
              }
              else {
                submissionData.data[component.key] = value;
              }
            }
          }, true);

          angular.forEach($scope.submission.data, function(value, key) {
            submissionData.data[key] = value;

            // Setup the submission access.
            var perm = defaultPermissions[key];
            if (perm) {
              submissionData.access = submissionData.access || [];

              // Coerce value into an array for plucking.
              if (!(value instanceof Array)) {
                value = [value];
              }

              // Try to find and update an existing permission.
              var found = false;
              submissionData.access.forEach(function(permission) {
                if (permission.type === perm) {
                  found = true;
                  permission.resources = permission.resources || [];
                  permission.resources.concat(grabIds(value));
                }
              });

              // Add a permission, because one was not found.
              if (!found) {
                submissionData.access.push({
                  type: perm,
                  resources: grabIds(value)
                });
              }
            }
          });
          // Strip out any angular keys.
          submissionData = angular.copy(submissionData);

          var submitEvent = $scope.$emit('formSubmit', submissionData);
          if (submitEvent.defaultPrevented) {
              // Listener wants to cancel the form submission
              return;
          }

          var onDone = function(submission) {
            if ($scope.storage && !$scope.readOnly) {
              localStorage.setItem($scope.storage, '');
            }
            $scope.showAlerts({
              type: 'success',
              message: 'Submission Complete!'
            });
            $scope.$emit('formSubmission', submission);
          };

          // Save to specified action.
          if ($scope.action) {
            var method = submissionData._id ? 'put' : 'post';
            $http[method]($scope.action, submissionData).then(function(submission) {
              Formio.clearCache();
              onDone(submission);
            }, FormioScope.onError($scope, $element));
          }
          else if ($scope.formio && !$scope.formio.noSubmit) {
            $scope.formio.saveSubmission(submissionData).then(onDone).catch(FormioScope.onError($scope, $element));
          }
          else {
            onDone(submissionData);
          }
        };

        $scope.cancel = function() {
          $scope.clear();
          showPage(true);
          $scope.$emit('cancel');
        };

        $scope.pageHasErrors = {};
        $scope.pageWasVisited = {};

        // Move onto the next page.
        $scope.next = function() {
          var errors = $scope.checkErrors();
          if (errors) {
            $scope.pageHasErrors[$scope.currentPage] = true;
            if (!$scope.formioOptions.wizardFreeNavigation) {
              return;
            }
          }
          else {
            $scope.pageHasErrors[$scope.currentPage] = false;
          }
          if ($scope.currentPage >= ($scope.pages.length - 1)) {
            return;
          }
          $scope.currentPage++;
          showPage(true);
          $scope.$emit('wizardNext', $scope.currentPage);
        };

        // Move onto the previous page.
        $scope.prev = function() {
          if ($scope.currentPage < 1) {
            return;
          }
          $scope.currentPage--;
          showPage(true);
          $scope.$emit('wizardPrev', $scope.currentPage);
        };

        $scope.goto = function(page) {
          if (page < 0) {
            return;
          }
          if (page >= $scope.pages.length) {
            return;
          }
          var errors = $scope.checkErrors();
          $scope.pageHasErrors[$scope.currentPage] = errors;
          $scope.currentPage = page;
          showPage(true);
        };

        $scope.isValid = function() {
          return getForm().$valid;
        };

        $scope.$on('wizardGoToPage', function(event, page) {
          $scope.goto(page);
        });

        var updatePages = function() {
          if ($scope.pages.length > 6) {
            $scope.margin = ((1 - ($scope.pages.length * 0.0833333333)) / 2) * 100;
            $scope.colclass = 'col-sm-1';
          }
          else {
            $scope.margin = ((1 - ($scope.pages.length * 0.1666666667)) / 2) * 100;
            $scope.colclass = 'col-sm-2';
          }
        };

        var allPages = [];
        var hasConditionalPages = false;
        var setForm = function(form) {
          $scope.pages = [];
          angular.forEach(form.components, function(component) {
            // Only include panels for the pages.
            if (component.type === 'panel') {
              if (!$scope.hasTitles && component.title) {
                $scope.hasTitles = true;
              }
              if (component.customConditional) {
                hasConditionalPages = true;
              }
              else if (component.conditional && component.conditional.when) {
                hasConditionalPages = true;
              }
              // Make sure this page is not in the hide compoenents array.
              if (
                ($scope.hideComponents) &&
                (component.key) &&
                ($scope.hideComponents.indexOf(component.key) !== -1)
              ) {
                return;
              }
              allPages.push(component);
              $scope.pages.push(component);
            }
          });

          // FOR-71
          if (!$scope.builder && hasConditionalPages) {
            $scope.$watch('submission.data', function(data) {
              var newPages = [];
              angular.forEach(allPages, function(page) {
                if (FormioUtils.isVisible(page, null, data)) {
                  newPages.push(page);
                }
              });
              $scope.pages = newPages;
              updatePages();
              setTimeout($scope.$apply.bind($scope), 10);
            }, true);
          }

          $scope.form = $scope.form ? angular.merge($scope.form, angular.copy(form)) : angular.copy(form);
          $scope.page = angular.copy(form);
          $scope.page.display = 'form';
          $scope.$emit('wizardFormLoad', form);
          updatePages();
          showPage();
        };

        // FOR-71
        if (!$scope.builder) {
          $scope.$watch('form', function(form) {
            if (
              $scope.src ||
              !form ||
              !Object.keys(form).length ||
              !form.components ||
              !form.components.length
            ) {
              return;
            }
            var formUrl = form.project ? '/project/' + form.project : '';
            formUrl += '/form/' + form._id;
            $scope.formio = new Formio(formUrl);
            setForm(form);
          });
        }

        // When the components length changes update the pages.
        $scope.$watch('form.components.length', updatePages);

        // Load the form.
        if ($scope.src) {
          $scope.formio = new Formio($scope.src);
          $scope.formio.loadForm().then(function(form) {
            setForm(form);
          });
        }
        else {
          $scope.src = '';
          $scope.formio = new Formio($scope.src);
        }
      }
    ]
  };
};
<|endoftext|>


<commit_before>

define([

	'underscore',
	'backbone',
	'marionette',
	'bootstrap',
	'templates',
	'leaflet',

	'view/loginModal',
	'view/userColumn',
	'view/linkColumn',
	'view/contribColumn',
	'view/editSettingColumn',
	'view/editPoiColumn',
	'view/editTileColumn',
	'view/tipOfTheDay',
],
function (

	_,
	Backbone,
	Marionette,
	Bootstrap,
	templates,
	L,

	LoginModalView,
	UserColumnView,
	LinkColumnView,
	ContribColumnView,
	EditSettingColumnView,
	EditPoiColumnView,
	EditTileColumnView,
	TipOfTheDayView
) {

	'use strict';

	return Marionette.LayoutView.extend({

		template: JST['main.html'],

		ui: {

			'map': '#main_map',
			'toolbarButtons': '.toolbar .toolbar_btn',

			'controlToolbar': '#control_toolbar',
			'zoomInButton': '#control_toolbar .zoom_in_btn',
			'zoomOutButton': '#control_toolbar .zoom_out_btn',
			'locateButton': '#control_toolbar .locate_btn',
			'controlPoiButton': '#control_toolbar .poi_btn',
			'controlTileButton': '#control_toolbar .tile_btn',

			'userToolbar': '#user_toolbar',
			'loginButton': '#user_toolbar .login_btn',
			'userButton': '#user_toolbar .user_btn',
			'linkButton': '#user_toolbar .link_btn',
			'contribButton': '#user_toolbar .contrib_btn',
			'editButton': '#user_toolbar .edit_btn',

			'helpToolbar': '#help_toolbar',
			'helpButton': '#help_toolbar .help_btn',

			'editToolbar': '#edit_toolbar',
			'editSettingButton': '#edit_toolbar .setting_btn',
			'editPoiButton': '#edit_toolbar .poi_btn',
			'editTileButton': '#edit_toolbar .tile_btn',
		},

		regions: {

			'loginModal': '#rg_login_modal',

			'userColumn': '#rg_user_column',
			'linkColumn': '#rg_link_column',
			'contribColumn': '#rg_contrib_column',
			'editSettingColumn': '#rg_edit_setting_column',
			'editPoiColumn': '#rg_edit_poi_column',
			'editTileColumn': '#rg_edit_tile_column',

			'tipOfTheDay': '#rg_tip_of_the_day',
		},

		events: {

			'click @ui.zoomInButton': 'onZoomIn',
			'click @ui.zoomOutButton': 'onZoomOut',

			'click @ui.loginButton': 'onClickLogin',
			'click @ui.userButton': 'onClickUser',
			'click @ui.linkButton': 'onClickLink',
			'click @ui.contribButton': 'onClickContrib',
			'click @ui.editButton': 'onClickEdit',
			'click @ui.editSettingButton': 'onClickEditSetting',
			'click @ui.editPoiButton': 'onClickEditPoi',
			'click @ui.editTileButton': 'onClickEditTile',
		},

		initialize: function () {

			var self = this;

			this._radio = Backbone.Wreqr.radio.channel('global');
		},

		onRender: function () {

			this.ui.toolbarButtons.tooltip({

				'container': 'body',
				'delay': {

					'show': 500,
					'hide': 0
				}
			})
			.on('click', function () {

				$(this).blur();
			});

			if ( this._radio.reqres.request('var', 'isLogged') ) {

				var user = this._radio.reqres.request('model', 'user'),
				avatar = user.get('avatar'),
				letters = user.get('displayName')
				.toUpperCase()
				.split(' ')
				.splice(0, 2)
				.map(function (name) {

					return name[0];
				})
				.join('');

				if (avatar) {

					this.ui.userButton
					.addClass('avatar')
					.html('');
				}
				else {

					this.ui.userButton
					.removeClass('avatar')
					.html(letters);
				}

				this.ui.loginButton.addClass('hide');
				this.ui.userButton.removeClass('hide');
			}
			else {

				this.ui.loginButton.removeClass('hide');
				this.ui.userButton.addClass('hide');
			}

			this._userColumnView = new UserColumnView();
			this._linkColumnView = new LinkColumnView();
			this._contribColumnView = new ContribColumnView();
			this._editSettingColumnView = new EditSettingColumnView();
			this._editPoiColumnView = new EditPoiColumnView();
			this._editTileColumnView = new EditTileColumnView();

			this.getRegion('userColumn').show( this._userColumnView );
			this.getRegion('linkColumn').show( this._linkColumnView );
			this.getRegion('contribColumn').show( this._contribColumnView );
			this.getRegion('editSettingColumn').show( this._editSettingColumnView );
			this.getRegion('editPoiColumn').show( this._editPoiColumnView );
			this.getRegion('editTileColumn').show( this._editTileColumnView );

			this.getRegion('tipOfTheDay').show( new TipOfTheDayView() );
		},

		onShow: function () {

			this._map = L.map(this.ui.map[0], { 'zoomControl': false });

			this._map.setView([44.82921, -0.5834], 12);

			L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

				'attribution': '© OpenStreetMap'
			})
			.addTo(this._map);
		},

		onZoomIn: function () {

			this._map.zoomIn();
		},

		onZoomOut: function () {

			this._map.zoomOut();
		},

		onClickLogin: function () {

			var self = this;

			this._loginModalView = new LoginModalView();

			this.getRegion('loginModal').show( this._loginModalView );
		},

		onClickUser: function () {

			this._userColumnView.open();
		},

		onClickLink: function () {

			this._linkColumnView.open();
		},

		onClickContrib: function () {

			this._contribColumnView.open();
		},

		onClickEdit: function () {

			this.ui.editToolbar.toggleClass('open');
		},

		onClickEditSetting: function () {

			this._editSettingColumnView.open();
		},

		onClickEditPoi: function () {

			this._editPoiColumnView.open();
		},

		onClickEditTile: function () {

			this._editTileColumnView.open();
		},
	});
});
<commit_msg>Display name's letters up to three<commit_after>

define([

	'underscore',
	'backbone',
	'marionette',
	'bootstrap',
	'templates',
	'leaflet',

	'view/loginModal',
	'view/userColumn',
	'view/linkColumn',
	'view/contribColumn',
	'view/editSettingColumn',
	'view/editPoiColumn',
	'view/editTileColumn',
	'view/tipOfTheDay',
],
function (

	_,
	Backbone,
	Marionette,
	Bootstrap,
	templates,
	L,

	LoginModalView,
	UserColumnView,
	LinkColumnView,
	ContribColumnView,
	EditSettingColumnView,
	EditPoiColumnView,
	EditTileColumnView,
	TipOfTheDayView
) {

	'use strict';

	return Marionette.LayoutView.extend({

		template: JST['main.html'],

		ui: {

			'map': '#main_map',
			'toolbarButtons': '.toolbar .toolbar_btn',

			'controlToolbar': '#control_toolbar',
			'zoomInButton': '#control_toolbar .zoom_in_btn',
			'zoomOutButton': '#control_toolbar .zoom_out_btn',
			'locateButton': '#control_toolbar .locate_btn',
			'controlPoiButton': '#control_toolbar .poi_btn',
			'controlTileButton': '#control_toolbar .tile_btn',

			'userToolbar': '#user_toolbar',
			'loginButton': '#user_toolbar .login_btn',
			'userButton': '#user_toolbar .user_btn',
			'linkButton': '#user_toolbar .link_btn',
			'contribButton': '#user_toolbar .contrib_btn',
			'editButton': '#user_toolbar .edit_btn',

			'helpToolbar': '#help_toolbar',
			'helpButton': '#help_toolbar .help_btn',

			'editToolbar': '#edit_toolbar',
			'editSettingButton': '#edit_toolbar .setting_btn',
			'editPoiButton': '#edit_toolbar .poi_btn',
			'editTileButton': '#edit_toolbar .tile_btn',
		},

		regions: {

			'loginModal': '#rg_login_modal',

			'userColumn': '#rg_user_column',
			'linkColumn': '#rg_link_column',
			'contribColumn': '#rg_contrib_column',
			'editSettingColumn': '#rg_edit_setting_column',
			'editPoiColumn': '#rg_edit_poi_column',
			'editTileColumn': '#rg_edit_tile_column',

			'tipOfTheDay': '#rg_tip_of_the_day',
		},

		events: {

			'click @ui.zoomInButton': 'onZoomIn',
			'click @ui.zoomOutButton': 'onZoomOut',

			'click @ui.loginButton': 'onClickLogin',
			'click @ui.userButton': 'onClickUser',
			'click @ui.linkButton': 'onClickLink',
			'click @ui.contribButton': 'onClickContrib',
			'click @ui.editButton': 'onClickEdit',
			'click @ui.editSettingButton': 'onClickEditSetting',
			'click @ui.editPoiButton': 'onClickEditPoi',
			'click @ui.editTileButton': 'onClickEditTile',
		},

		initialize: function () {

			var self = this;

			this._radio = Backbone.Wreqr.radio.channel('global');
		},

		onRender: function () {

			this.ui.toolbarButtons.tooltip({

				'container': 'body',
				'delay': {

					'show': 500,
					'hide': 0
				}
			})
			.on('click', function () {

				$(this).blur();
			});

			if ( this._radio.reqres.request('var', 'isLogged') ) {

				var user = this._radio.reqres.request('model', 'user'),
				avatar = user.get('avatar'),
				letters = user.get('displayName')
				.toUpperCase()
				.split(' ')
				.splice(0, 3)
				.map(function (name) {

					return name[0];
				})
				.join('');

				if (letters.length > 3) {

					letters = letters[0];
				}

				if (avatar) {

					this.ui.userButton
					.addClass('avatar')
					.html('');
				}
				else {

					this.ui.userButton
					.removeClass('avatar')
					.html(letters);
				}

				this.ui.loginButton.addClass('hide');
				this.ui.userButton.removeClass('hide');
			}
			else {

				this.ui.loginButton.removeClass('hide');
				this.ui.userButton.addClass('hide');
			}

			this._userColumnView = new UserColumnView();
			this._linkColumnView = new LinkColumnView();
			this._contribColumnView = new ContribColumnView();
			this._editSettingColumnView = new EditSettingColumnView();
			this._editPoiColumnView = new EditPoiColumnView();
			this._editTileColumnView = new EditTileColumnView();

			this.getRegion('userColumn').show( this._userColumnView );
			this.getRegion('linkColumn').show( this._linkColumnView );
			this.getRegion('contribColumn').show( this._contribColumnView );
			this.getRegion('editSettingColumn').show( this._editSettingColumnView );
			this.getRegion('editPoiColumn').show( this._editPoiColumnView );
			this.getRegion('editTileColumn').show( this._editTileColumnView );

			this.getRegion('tipOfTheDay').show( new TipOfTheDayView() );
		},

		onShow: function () {

			this._map = L.map(this.ui.map[0], { 'zoomControl': false });

			this._map.setView([44.82921, -0.5834], 12);

			L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

				'attribution': '© OpenStreetMap'
			})
			.addTo(this._map);
		},

		onZoomIn: function () {

			this._map.zoomIn();
		},

		onZoomOut: function () {

			this._map.zoomOut();
		},

		onClickLogin: function () {

			var self = this;

			this._loginModalView = new LoginModalView();

			this.getRegion('loginModal').show( this._loginModalView );
		},

		onClickUser: function () {

			this._userColumnView.open();
		},

		onClickLink: function () {

			this._linkColumnView.open();
		},

		onClickContrib: function () {

			this._contribColumnView.open();
		},

		onClickEdit: function () {

			this.ui.editToolbar.toggleClass('open');
		},

		onClickEditSetting: function () {

			this._editSettingColumnView.open();
		},

		onClickEditPoi: function () {

			this._editPoiColumnView.open();
		},

		onClickEditTile: function () {

			this._editTileColumnView.open();
		},
	});
});
<|endoftext|>


<commit_before>export const HeathBarX = 650;
export const HeathBarY = 565;

export const HeathBarConfig = {
  x: HeathBarX,
  y: HeathBarY,
  bar: { color: "#43d637" },
  bg: { color: "#8A0707" }
};
<commit_msg>constants<commit_after>export const HeathBarX = 650;
export const HeathBarY = 565;

export const HeathBarConfig = {
  x: HeathBarX,
  y: HeathBarY,
  bar: { color: "#43d637" },
  bg: { color: "#8A0707" },
  animationDuration: 50
};
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _fs = require('fs');

var fs = _interopRequireWildcard(_fs);

var _ghPages = require('gh-pages');

var ghpages = _interopRequireWildcard(_ghPages);

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _logWith = require('log-with');

var _logWith2 = _interopRequireDefault(_logWith);

var _mkdirp = require('mkdirp');

var _mkdirp2 = _interopRequireDefault(_mkdirp);

var _path = require('path');

var path = _interopRequireWildcard(_path);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

const logger = (0, _logWith2.default)(module);

class Representation {
  constructor(config) {
    this.sources = [];
    let opts = config;
    if (_lodash2.default.isString(config)) {
      opts = {
        folder: config
      };
    }
    this.fileName = opts.fileName || 'me.json';
    this.folder = opts.folder;
    this.config = opts;
  }

  write(data) {
    const filePath = path.join(process.cwd(), this.folder, this.fileName);
    logger.debug('File created at', filePath);
    _mkdirp2.default.sync(path.dirname(filePath));
    fs.writeFileSync(filePath, JSON.stringify(data, null, 4));
    return this;
  }

  addSource(source) {
    this.sources.push(source);
    return this;
  }

  build() {
    var _this = this;

    return _asyncToGenerator(function* () {
      const sources = _lodash2.default.map(_this.sources, (() => {
        var _ref = _asyncToGenerator(function* (source) {
          try {
            return source.load();
          } catch (e) {
            return null;
          }
        });

        return function (_x) {
          return _ref.apply(this, arguments);
        };
      })());
      _this.payload = _lodash2.default.compact((yield Promise.all(sources)));
      return _this;
    })();
  }

  generate() {
    var _this2 = this;

    return _asyncToGenerator(function* () {
      yield _this2.build();
      _this2.write(_this2.payload || {});
      return _this2;
    })();
  }

  publish() {
    var _this3 = this;

    return _asyncToGenerator(function* () {
      const promise = new Promise(function (resolve, reject) {
        return ghpages.publish(_this3.folder, _this3.config.publish || {}, function (err) {
          if (err) {
            reject(err);
            return;
          }
          resolve();
        });
      });
      yield promise;
      return _this3;
    })();
  }
}

exports.default = Representation;<commit_msg>update dist<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _fs = require('fs');

var fs = _interopRequireWildcard(_fs);

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _logWith = require('log-with');

var _logWith2 = _interopRequireDefault(_logWith);

var _mkdirp = require('mkdirp');

var _mkdirp2 = _interopRequireDefault(_mkdirp);

var _path = require('path');

var path = _interopRequireWildcard(_path);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

const logger = (0, _logWith2.default)(module);

class Representation {
  constructor(config) {
    this.options = _lodash2.default.extend(Representation.getOptions(), config);
  }

  static getOptions() {
    return {
      folder: 'build',
      file: 'me.json'
    };
  }

  write(data) {
    const { folder, file } = this.options;
    const filePath = path.join(process.cwd(), folder, file);
    logger.debug('File created at', filePath);
    _mkdirp2.default.sync(path.dirname(filePath));
    fs.writeFileSync(filePath, JSON.stringify(data, null, 4));
  }

  build() {
    var _this = this;

    return _asyncToGenerator(function* () {
      const sources = _lodash2.default.chain(_this.options.sources).map((() => {
        var _ref = _asyncToGenerator(function* (option, sourceName) {
          const { Source } = yield Promise.resolve().then(() => require(`representation-source-${sourceName}`));
          const source = new Source(option);
          return source.load();
        });

        return function (_x, _x2) {
          return _ref.apply(this, arguments);
        };
      })()).value();
      const payload = _lodash2.default.compact((yield Promise.all(sources)));
      _this.write(payload);
    })();
  }

}

exports.default = Representation;<|endoftext|>


<commit_before>// ------------------------------------------------------------------------------
//
// LightBox
//
// ------------------------------------------------------------------------------

define([ "jquery", "lib/mixins/flyout", "lib/utils/viewport_helper", "lib/utils/template" ], function($, asFlyout, viewportHelper, Template) {

  "use strict";

  // @args = {}
  // el: {string} selector for parent element
  var LightBox = function(args) {
    this.customClass = args.customClass;
    this.$listener = $(args.$listener || "#js-row--content");
    this.preloader = args.preloader || false;
    this.$el = $(args.el);
    this.$el && this.init();
  },
  _this,
  $window = $(window);

  // -------------------------------------------------------------------------
  // Mixins
  // -------------------------------------------------------------------------
  // The argument with the facet is required at the moment and is soon to be
  // removed from the flyout mixin.
  asFlyout.call(LightBox.prototype, { facet: ".to-be-removed", $listener: $(".lightbox__content") });

  // -------------------------------------------------------------------------
  // Initialise
  // -------------------------------------------------------------------------

  LightBox.prototype.init = function() {
    var $body = $("body");

    _this = this;

    this.$lightbox = $(".lightbox");
    this.$lightboxContent = this.$lightbox.find(".lightbox__content");

    if (!this.$lightbox.length) {
      this.$lightboxContent = $("
");
      this.$lightbox = $("
");

      this.customClass && this.$lightbox.addClass(this.customClass);

      this.$lightbox.append(this.$lightboxContent);

      $body.prepend(this.$lightbox);

      // Just in case there are defined dimensions already specified.
      this._centerLightbox();
    }

    this.$lightbox.css({
      height: $body.height(),
      width: $body.width()
    });
    if (this.preloader) {
      this.preloaderTmpl = Template.render($("#tmpl-preloader").text(), {});
    }

    this.listen();
  };

  // -------------------------------------------------------------------------
  // Subscribe to Events
  // -------------------------------------------------------------------------

  LightBox.prototype.listen = function() {

    this.$listener.on(":lightbox/updateContent", function(event, content) {
      _this._updateContent(content);
    });

    this.$listener.on(":lightbox/updateContentAjax", function(event, url) {
      _this._updateContentAjax(url);
    });

    this.$listener.on(":flyout/close", function() {
      _this.$lightboxContent.empty();
    });

    // this.$lightbox.on("click", function(e) {
    //   if (e.target == e.currentTarget) {
    //     _this.$listener.trigger(":toggleActive/update", _this.$el);
    //   }
    // });

    this.$listener.on(":layer/received", function(event, content) {
      _this._updateContent(content);
    });

    this.$listener.on(":htmlpage/received", function(event, content) {
      _this._updateContent(content);
    });

  };

  // -------------------------------------------------------------------------
  // Private Functions
  // -------------------------------------------------------------------------

  LightBox.prototype._updateContentAjax = function(url) {
    if (this.preloader){

      _this.$lightboxContent.html( this.preloaderTmpl );
      _this.$lightbox.addClass("is-loading");
      _this._centerLightbox();
    }

    $("#js-card-holder").trigger(":layer/request", { url: url });
  };

  // @content: {string} the content to dump into the lightbox.
  LightBox.prototype._updateContent = function(content) {
    _this.$listener.trigger(":lightbox/contentUpdated", _this.$el);
    _this.$lightbox.removeClass("is-loading");
    _this.$lightboxContent.html(content);
    _this._centerLightbox();
  };

  LightBox.prototype._centerLightbox = function() {
    this.$lightboxContent.css({
      left: this._centeredLeftPosition(),
      top: this._centeredTopPosition()
    });
  };

  LightBox.prototype._centeredLeftPosition = function() {
    var lightboxW = this.$lightboxContent.width(),
        left = $window.scrollLeft() + (viewportHelper.viewport().width / 2) - (lightboxW / 2);

    if (lightboxW > viewportHelper.viewport().width) {
      left = $window.scrollLeft();
    }

    return left;
  };

  LightBox.prototype._centeredTopPosition = function() {
    var lightboxH = this.$lightboxContent.height(),
        top = $window.scrollTop() + (viewportHelper.viewport().height / 2) - (lightboxH / 2);

    if (lightboxH > viewportHelper.viewport().height) {
      top = $window.scrollTop();
    }

    return top;
  };

  // This is useful for testing. Do not remove.
  LightBox.prototype._viewportDimensions = function() {
    return {
      h: $window.height(),
      w: $window.width()
    };
  };

  LightBox.prototype._getPreloaderHTML = function() {
    return "

";
  };

  // Self instantiate if the default class is used.
  if ($(".js-lightbox-toggle").length) {
    var $lightboxToggle = $(".js-lightbox-toggle");
    new LightBox({
      customClass: $lightboxToggle.data("lightbox-class"),
      preloader: $lightboxToggle.data("lightbox-preloader"),
      el: ".js-lightbox-toggle"
    });
  }

  return LightBox;

});
<commit_msg>Template for preloader instead of hardcoded HTML<commit_after>// ------------------------------------------------------------------------------
//
// LightBox
//
// ------------------------------------------------------------------------------
define([ "jquery", "lib/mixins/flyout", "lib/utils/viewport_helper", "lib/utils/template" ], function($, asFlyout, viewportHelper, Template) {

  "use strict";

  // @args = {}
  // el: {string} selector for parent element
  var LightBox = function(args) {
    this.customClass = args.customClass;
    this.$listener = $(args.$listener || "#js-row--content");
    this.preloader = args.preloader || false;
    this.$el = $(args.el);
    this.$el && this.init();
  },
  _this,
  $window = $(window);

  // -------------------------------------------------------------------------
  // Mixins
  // -------------------------------------------------------------------------
  // The argument with the facet is required at the moment and is soon to be
  // removed from the flyout mixin.
  asFlyout.call(LightBox.prototype, { facet: ".to-be-removed", $listener: $(".lightbox__content") });

  // -------------------------------------------------------------------------
  // Initialise
  // -------------------------------------------------------------------------

  LightBox.prototype.init = function() {
    var $body = $("body");

    _this = this;

    this.$lightbox = $(".lightbox");
    this.$lightboxContent = this.$lightbox.find(".lightbox__content");

    if (!this.$lightbox.length) {
      this.$lightboxContent = $("
");
      this.$lightbox = $("
");

      this.customClass && this.$lightbox.addClass(this.customClass);

      this.$lightbox.append(this.$lightboxContent);

      $body.prepend(this.$lightbox);

      // Just in case there are defined dimensions already specified.
      this._centerLightbox();
    }

    this.$lightbox.css({
      height: $body.height(),
      width: $body.width()
    });
    if (this.preloader) {
      this.preloaderTmpl = Template.render($("#tmpl-preloader").text(), {});
    }

    this.listen();
  };

  // -------------------------------------------------------------------------
  // Subscribe to Events
  // -------------------------------------------------------------------------

  LightBox.prototype.listen = function() {

    this.$listener.on(":lightbox/updateContent", function(event, content) {
      _this._updateContent(content);
    });

    this.$listener.on(":lightbox/updateContentAjax", function(event, url) {
      _this._updateContentAjax(url);
    });

    this.$listener.on(":flyout/close", function() {
      _this.$lightboxContent.empty();
    });

    // this.$lightbox.on("click", function(e) {
    //   if (e.target == e.currentTarget) {
    //     _this.$listener.trigger(":toggleActive/update", _this.$el);
    //   }
    // });

    this.$listener.on(":layer/received", function(event, content) {
      _this._updateContent(content);
    });

    this.$listener.on(":htmlpage/received", function(event, content) {
      _this._updateContent(content);
    });

  };

  // -------------------------------------------------------------------------
  // Private Functions
  // -------------------------------------------------------------------------

  LightBox.prototype._updateContentAjax = function(url) {
    if (this.preloader){
      _this.$lightboxContent.html( this.preloaderTmpl );
      _this.$lightbox.addClass("is-loading");
      _this._centerLightbox();
    }

    $("#js-card-holder").trigger(":layer/request", { url: url });
  };

  // @content: {string} the content to dump into the lightbox.
  LightBox.prototype._updateContent = function(content) {
    _this.$listener.trigger(":lightbox/contentUpdated", _this.$el);
    _this.$lightbox.removeClass("is-loading");
    _this.$lightboxContent.html(content);
    _this._centerLightbox();
  };

  LightBox.prototype._centerLightbox = function() {
    this.$lightboxContent.css({
      left: this._centeredLeftPosition(),
      top: this._centeredTopPosition()
    });
  };

  LightBox.prototype._centeredLeftPosition = function() {
    var lightboxW = this.$lightboxContent.width(),
        left = $window.scrollLeft() + (viewportHelper.viewport().width / 2) - (lightboxW / 2);

    if (lightboxW > viewportHelper.viewport().width) {
      left = $window.scrollLeft();
    }

    return left;
  };

  LightBox.prototype._centeredTopPosition = function() {
    var lightboxH = this.$lightboxContent.height(),
        top = $window.scrollTop() + (viewportHelper.viewport().height / 2) - (lightboxH / 2);

    if (lightboxH > viewportHelper.viewport().height) {
      top = $window.scrollTop();
    }

    return top;
  };

  // This is useful for testing. Do not remove.
  LightBox.prototype._viewportDimensions = function() {
    return {
      h: $window.height(),
      w: $window.width()
    };
  };

  // Self instantiate if the default class is used.
  if ($(".js-lightbox-toggle").length) {
    var $lightboxToggle = $(".js-lightbox-toggle");
    new LightBox({
      customClass: $lightboxToggle.data("lightbox-class"),
      preloader: $lightboxToggle.data("lightbox-preloader"),
      el: ".js-lightbox-toggle"
    });
  }

  return LightBox;

});
<|endoftext|>


<commit_before>
var gulp        = require('gulp'),
    $           = require('gulp-load-plugins')(),

    // TODO: remove
    sequence    = require('gulp-sequence'),
    jshint      = require('gulp-jshint'), // jshint-stylish
    lintspaces  = require('gulp-lintspaces'),
    rev         = require('gulp-rev'),
    revReplace  = require('gulp-rev-replace'),
    useref      = require('gulp-useref'),
    filter      = require('gulp-filter'),
    uglify      = require('gulp-uglify'),
    csso        = require('gulp-csso'),
    minifyHtml  = require('gulp-minify-html'),

    // TODO: added to $
    lazypipe    = require('lazypipe'),
    del         = require('del'),
    browserSync = require('browser-sync'),
    reload      = browserSync.reload;

    $.pkg         = require('./package.json');

    // shared streams
    $.streams     = {};

//------------------------------------------------------------------------------
// @begin: utils
(function() {

/**
  * Log a message or series of messages using chalk's blue color.
  * Can pass in a string, object or array.
  */
$.log = function(msg) {
  if (typeof(msg) === 'object') {
    for (var item in msg) {
      if (msg.hasOwnProperty(item)) {
        $.util.log($.util.colors.blue(msg[item]));
      }
    }
  } else {
    $.util.log($.util.colors.blue(msg));
  }
};

//---

$.projectInfoMsg = function() {
  $.log('');
  $.log('project: ' + $.pkg.name + ' v' + $.pkg.version);
  $.log('description: ' + $.pkg.description);
  $.log('');
};

})();
// @end: utils
//------------------------------------------------------------------------------
// configs

// TODO: define

//==============================================================================
// @begin: gulp tasks ==========================================================
//==============================================================================
// @begin: clean

gulp.task('clean:dist', del.bind(null, [ 'dist' ]));

gulp.task('clean:bower', del.bind(null, [ '.local/bower' ]));

gulp.task('clean', ['clean:dist', 'clean:bower']);

// @end: clean
//------------------------------------------------------------------------------
// @begin: bower

gulp.task('bower:jquery', function() {
  return gulp.src('bower_components/jquery/dist/*.{js,map}')
    .pipe(gulp.dest('.local/bower/vendor/jquery'));
});

gulp.task('bower:dev', sequence('clean:bower', 'bower:jquery'));

gulp.task('bower:dist', ['bower:dev'], function() {
  return gulp.src('.local/bower/**/*')
    .pipe(gulp.dest('dist'));
});

// @end: bower
//------------------------------------------------------------------------------
// @begin: jshint

gulp.task('jshint:tools', function() {
  return gulp.src('gulpfile.js')
    .pipe( jshint() )
    .pipe( jshint.reporter('jshint-stylish') )
    .pipe( jshint.reporter('fail') );
});

gulp.task('jshint:project', function() {
    return gulp.src('src/**/*.js')
    .pipe( jshint() )
    .pipe( jshint.reporter('jshint-stylish') )
    .pipe( jshint.reporter('fail') );
});

gulp.task('jshint', ['jshint:tools', 'jshint:project']);

// @end: jshint
//------------------------------------------------------------------------------
// @begin: lintspaces

gulp.task('lintspaces:tools', function() {
  return gulp.src('gulpfile.js')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project:js', function() {
  return gulp.src('src/**/*.js')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project:css', function() {
  return gulp.src('src/**/*.css')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project:html', function() {
  return gulp.src('src/**/*.html')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project', [
  'lintspaces:project:js',
  'lintspaces:project:css',
  'lintspaces:project:html'
]);

gulp.task('lintspaces', ['lintspaces:tools', 'lintspaces:project']);

// @end: lintspaces
//------------------------------------------------------------------------------
// validate
gulp.task('validate', ['jshint', 'lintspaces']);

//------------------------------------------------------------------------------
// @begin: build

gulp.task('build:index', function() {

  var jsFilter       = filter( '**/*.js' ),
      cssFilter      = filter( '**/*.css' ),
      htmlFilter     = filter( '**/*.html' ),
      userefAssets   = useref.assets(),
      minifyHtmlOpts = {
        conditionals: true,
        spare:true
      };

  return gulp.src( 'src/index.html' )
    .pipe( userefAssets ) // Concatenate with gulp-useref
    .pipe( jsFilter )
    .pipe( uglify() ) // Minify any javascript sources
    .pipe( jsFilter.restore() )
    .pipe( cssFilter )
    .pipe( csso() ) // Minify any CSS sources
    .pipe( cssFilter.restore() )
    .pipe( rev() ) // Rename the concatenated files
    .pipe( userefAssets.restore() )
    .pipe( useref() )
    .pipe( revReplace() ) // Substitute in new filenames
    .pipe( htmlFilter )
    .pipe( minifyHtml( minifyHtmlOpts ) )
    .pipe( htmlFilter.restore() )
    .pipe( gulp.dest('dist') );

});

gulp.task('build', sequence(['clean:dist', 'validate'], ['build:index', 'bower:dist']));

// @end: build
//------------------------------------------------------------------------------
// @begin: webserver

gulp.task('webserver:dist', ['build'], function() {

  browserSync({
    ui: false,
    port: 1337,
    server:{
      baseDir: 'dist'
    }
  });

});

gulp.task('webserver:dev', ['validate', 'bower:dev'], function() {

  browserSync({
    port: 1337,
    server:{
      baseDir: ['src', '.local/bower']
    }
  });

});

// @end: webserver
//------------------------------------------------------------------------------
// @begin: watch

gulp.task('watch', ['webserver:dev'], function() {

  gulp.watch(['src/**/*.html'], ['wf:project:html']);

  gulp.watch(['src/**/*.js'], ['wf:project:js']);

  gulp.watch(['src/**/*.css'], ['wf:project:css']);

});

gulp.task('wf:bs:reload', function() {
  reload();
});

gulp.task('wf:project:html', function( done ) {
  sequence(
    'lintspaces:project:html',
    'wf:bs:reload',
    done
  );
});

gulp.task('wf:project:js', function( done ) {
  sequence(
    [
      'jshint:project',
      'lintspaces:project:js'
    ],
    'wf:bs:reload',
    done
  );
});

gulp.task('wf:project:css', function( done ) {
  sequence(
    'lintspaces:project:css',
    'wf:bs:reload',
    done
  );
});

// @end: watch
//------------------------------------------------------------------------------
// @begin: main

// TODO: remove
gulp.task('temp', function() {
  $.projectInfoMsg();
});

gulp.task('default', ['watch'], function() {
  $.projectInfoMsg();
});

gulp.task('release', ['build'], function() {
  $.projectInfoMsg();
});

gulp.task('preview', ['webserver:dist'], function() {
  $.projectInfoMsg();
});

// @end: main
//==============================================================================
// @end: gulp tasks ============================================================
//==============================================================================
<commit_msg>gulp step 02 - clean tasks updated<commit_after>
var gulp        = require('gulp'),
    $           = require('gulp-load-plugins')(),

    // TODO: remove
    sequence    = require('gulp-sequence'),
    jshint      = require('gulp-jshint'), // jshint-stylish
    lintspaces  = require('gulp-lintspaces'),
    rev         = require('gulp-rev'),
    revReplace  = require('gulp-rev-replace'),
    useref      = require('gulp-useref'),
    filter      = require('gulp-filter'),
    uglify      = require('gulp-uglify'),
    csso        = require('gulp-csso'),
    minifyHtml  = require('gulp-minify-html'),

    // TODO: added to $
    browserSync = require('browser-sync'),
    reload      = browserSync.reload;

    $.pkg         = require('./package.json');
    $.del         = require('del');
    $.lazypipe    = require('lazypipe')

    // shared streams
    $.streams     = {};

//------------------------------------------------------------------------------
// @begin: utils
(function() {

/**
  * Log a message or series of messages using chalk's blue color.
  * Can pass in a string, object or array.
  */
$.log = function(msg) {
  if (typeof(msg) === 'object') {
    for (var item in msg) {
      if (msg.hasOwnProperty(item)) {
        $.util.log($.util.colors.blue(msg[item]));
      }
    }
  } else {
    $.util.log($.util.colors.blue(msg));
  }
};

//---

$.projectInfoMsg = function() {
  $.log('');
  $.log('project: ' + $.pkg.name + ' v' + $.pkg.version);
  $.log('description: ' + $.pkg.description);
  $.log('');
};

})();
// @end: utils
//------------------------------------------------------------------------------
// configs

// TODO: define

//==============================================================================
// @begin: gulp tasks ==========================================================
//==============================================================================
// @begin: clean

gulp.task('clean:dist', $.del.bind(null, [ 'dist' ]));

gulp.task('clean:bower', $.del.bind(null, [ '.local/bower' ]));

gulp.task('clean', ['clean:dist', 'clean:bower']);

// @end: clean
//------------------------------------------------------------------------------
// @begin: bower

gulp.task('bower:jquery', function() {
  return gulp.src('bower_components/jquery/dist/*.{js,map}')
    .pipe(gulp.dest('.local/bower/vendor/jquery'));
});

gulp.task('bower:dev', sequence('clean:bower', 'bower:jquery'));

gulp.task('bower:dist', ['bower:dev'], function() {
  return gulp.src('.local/bower/**/*')
    .pipe(gulp.dest('dist'));
});

// @end: bower
//------------------------------------------------------------------------------
// @begin: jshint

gulp.task('jshint:tools', function() {
  return gulp.src('gulpfile.js')
    .pipe( jshint() )
    .pipe( jshint.reporter('jshint-stylish') )
    .pipe( jshint.reporter('fail') );
});

gulp.task('jshint:project', function() {
    return gulp.src('src/**/*.js')
    .pipe( jshint() )
    .pipe( jshint.reporter('jshint-stylish') )
    .pipe( jshint.reporter('fail') );
});

gulp.task('jshint', ['jshint:tools', 'jshint:project']);

// @end: jshint
//------------------------------------------------------------------------------
// @begin: lintspaces

gulp.task('lintspaces:tools', function() {
  return gulp.src('gulpfile.js')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project:js', function() {
  return gulp.src('src/**/*.js')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project:css', function() {
  return gulp.src('src/**/*.css')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project:html', function() {
  return gulp.src('src/**/*.html')
    .pipe( lintspaces({ editorconfig: '../.editorconfig' }) )
    .pipe( lintspaces.reporter() );
});

gulp.task('lintspaces:project', [
  'lintspaces:project:js',
  'lintspaces:project:css',
  'lintspaces:project:html'
]);

gulp.task('lintspaces', ['lintspaces:tools', 'lintspaces:project']);

// @end: lintspaces
//------------------------------------------------------------------------------
// validate
gulp.task('validate', ['jshint', 'lintspaces']);

//------------------------------------------------------------------------------
// @begin: build

gulp.task('build:index', function() {

  var jsFilter       = filter( '**/*.js' ),
      cssFilter      = filter( '**/*.css' ),
      htmlFilter     = filter( '**/*.html' ),
      userefAssets   = useref.assets(),
      minifyHtmlOpts = {
        conditionals: true,
        spare:true
      };

  return gulp.src( 'src/index.html' )
    .pipe( userefAssets ) // Concatenate with gulp-useref
    .pipe( jsFilter )
    .pipe( uglify() ) // Minify any javascript sources
    .pipe( jsFilter.restore() )
    .pipe( cssFilter )
    .pipe( csso() ) // Minify any CSS sources
    .pipe( cssFilter.restore() )
    .pipe( rev() ) // Rename the concatenated files
    .pipe( userefAssets.restore() )
    .pipe( useref() )
    .pipe( revReplace() ) // Substitute in new filenames
    .pipe( htmlFilter )
    .pipe( minifyHtml( minifyHtmlOpts ) )
    .pipe( htmlFilter.restore() )
    .pipe( gulp.dest('dist') );

});

gulp.task('build', sequence(['clean:dist', 'validate'], ['build:index', 'bower:dist']));

// @end: build
//------------------------------------------------------------------------------
// @begin: webserver

gulp.task('webserver:dist', ['build'], function() {

  browserSync({
    ui: false,
    port: 1337,
    server:{
      baseDir: 'dist'
    }
  });

});

gulp.task('webserver:dev', ['validate', 'bower:dev'], function() {

  browserSync({
    port: 1337,
    server:{
      baseDir: ['src', '.local/bower']
    }
  });

});

// @end: webserver
//------------------------------------------------------------------------------
// @begin: watch

gulp.task('watch', ['webserver:dev'], function() {

  gulp.watch(['src/**/*.html'], ['wf:project:html']);

  gulp.watch(['src/**/*.js'], ['wf:project:js']);

  gulp.watch(['src/**/*.css'], ['wf:project:css']);

});

gulp.task('wf:bs:reload', function() {
  reload();
});

gulp.task('wf:project:html', function( done ) {
  sequence(
    'lintspaces:project:html',
    'wf:bs:reload',
    done
  );
});

gulp.task('wf:project:js', function( done ) {
  sequence(
    [
      'jshint:project',
      'lintspaces:project:js'
    ],
    'wf:bs:reload',
    done
  );
});

gulp.task('wf:project:css', function( done ) {
  sequence(
    'lintspaces:project:css',
    'wf:bs:reload',
    done
  );
});

// @end: watch
//------------------------------------------------------------------------------
// @begin: main

// TODO: remove
gulp.task('temp', function() {
  $.projectInfoMsg();
});

gulp.task('default', ['watch'], function() {
  $.projectInfoMsg();
});

gulp.task('release', ['build'], function() {
  $.projectInfoMsg();
});

gulp.task('preview', ['webserver:dist'], function() {
  $.projectInfoMsg();
});

// @end: main
//==============================================================================
// @end: gulp tasks ============================================================
//==============================================================================
<|endoftext|>


<commit_before>'use strict'

/**
 * Module dependencies.
 */

import OrbitCameraController from 'axis3d/controls/orbit-camera'
import VignetteBackground from 'axis3d/backgrounds/vignette'
import AmbientLight from 'axis3d/light/ambient'
import Feedback from 'axis3d/feedback'
import Context from 'axis3d/context'
import Camera from 'axis3d/camera'
import Sphere from 'axis3d/mesh/sphere'
import Mouse from 'axis3d/input/mouse'
import Plane from 'axis3d/mesh/plane'
import Frame from 'axis3d/frame'
import quat from 'gl-quat'
import mat4 from 'gl-mat4'
import vec3 from 'gl-vec3'
import raf from 'raf'
import Box from 'axis3d/mesh/box'

const ctx = Context()

const background = VignetteBackground(ctx)
const feedback = Feedback(ctx)
const camera = Camera(ctx, {position: [1600, 1600, 1600]})
const world = Sphere(ctx, {
  wireframe: true,
  color: [0.8, 0.8, 0.85, .5],
  radius: 500,
})

const sphere = Sphere(ctx)
const light = AmbientLight(ctx)
const plane = Plane(ctx, {
  wireframe: true,
  segments: {x: 64, y: 64},
  color: [0.8, 0.8, 0.8, 1],
  size: {x: 300, y: 300},

  rotation: quat.multiply(
    [],
    quat.setAxisAngle([], [1, 0, 0], Math.PI/2),
    quat.setAxisAngle([], [0, 1, 0], Math.PI)
  ),
})

const frame = Frame(ctx)
const mouse = Mouse(ctx)
const box = Box(ctx, {position: [4, .5, 0]})
const controller = OrbitCameraController(ctx, {
  orientation: [Math.PI/8, -0.3, 0],
  inputs: {mouse},
  target: camera,
})

const position = [0, 0, 0]
const rotation = [0, 0, 0, 1]
const scale = [1, 1, 1]
const color = [0, 0, 0, 1]

const translate = (x, y, z) => {
  position[0] = x
  position[1] = y
  position[2] = z
}

Object.assign(window, {
  controller,
  feedback,
  camera,
  sphere,
  world,
  plane,
  frame,
  vec3,
  box,
  ctx,
})

// swap targets every 10s
window.target = sphere.position
let i = 0
setInterval(() => {
  target = i++ % 2 ? sphere.position : box.position
}, 10000)

frame(({time}) => {
  // vignette background effect
  const reduction = 2 - (0.5 + 0.5*Math.cos(time))
  color[0] = 0.025*time % 128
  color[1] = 0.025*time % 128
  color[2] = Math.sin(0.25*time) % 255
  background({reduction, color})

  // lerp into scene
  if (!mouse.wheel.deltaY) {
    vec3.lerp(camera.position, camera.position, [0, 0, 200], 0.0125)
  }

  // viewer
  const off = 20
  const d = 40
  let s = 0

  // lerp to target
  camera({target: vec3.lerp([], camera.target, target, 0.025)}, () => {
    // update controller state
    controller()

    // draw world
    world({rotation: quat.setAxisAngle([], [1, 0, 0], 0.05*time)}, ({model}) => {
      feedback({model})

      // draw plane in world
      plane()

      // orbit box around origin
      s = 2 + (0.5 - 0.5*Math.cos(time))
      translate(s + 300, s + 0.5, s + 10)
      vec3.transformQuat(
        position, position,
        quat.multiply(
          quat.setAxisAngle([], [1, 0, 0], 0.5*time),
          quat.setAxisAngle([], [0, 1, 0], 0.5*time),
          quat.setAxisAngle([], [0, 0, 1], 0.5*time))
      )

      // draw box with feedback
      s = off + (1.0 - 1.0*Math.cos(time))
      box({position}, ({model}) => {
        feedback({model, scale: [s, s, s]})
      })

      // oscillate sphere
      translate(s + (d - d*Math.sin(time)), s + (0.5 - 0.5*Math.cos(time)), 0)
      s = off + (0.5 - 0.5*Math.cos(time))
      // draw sphere with feedback
      sphere({position, color: [.5, .5, .25, 1]}, ({model}) => {
        feedback({model, scale: [s, s, s]})
      })
    })
  })
})
<commit_msg>tweak<commit_after>'use strict'

/**
 * Module dependencies.
 */

import OrbitCameraController from 'axis3d/controls/orbit-camera'
import VignetteBackground from 'axis3d/backgrounds/vignette'
import AmbientLight from 'axis3d/light/ambient'
import Feedback from 'axis3d/feedback'
import Context from 'axis3d/context'
import Camera from 'axis3d/camera'
import Sphere from 'axis3d/mesh/sphere'
import Mouse from 'axis3d/input/mouse'
import Plane from 'axis3d/mesh/plane'
import Frame from 'axis3d/frame'
import quat from 'gl-quat'
import mat4 from 'gl-mat4'
import vec3 from 'gl-vec3'
import raf from 'raf'
import Box from 'axis3d/mesh/box'

const ctx = Context()

const background = VignetteBackground(ctx)
const feedback = Feedback(ctx)
const camera = Camera(ctx, {position: [1600, 1600, 1600]})
const world = Sphere(ctx, {
  wireframe: true,
  color: [0.8, 0.8, 0.85, .5],
  radius: 500,
})

const sphere = Sphere(ctx)
const light = AmbientLight(ctx)
const plane = Plane(ctx, {
  wireframe: true,
  segments: {x: 64, y: 64},
  color: [0.8, 0.8, 0.8, 1],
  size: {x: 300, y: 300},

  rotation: quat.setAxisAngle([], [1, 0, 0], Math.PI/2),
})

const frame = Frame(ctx)
const mouse = Mouse(ctx)
const box = Box(ctx, {position: [4, .5, 0]})
const controller = OrbitCameraController(ctx, {
  orientation: [Math.PI/8, -0.3, 0],
  inputs: {mouse},
  target: camera,
})

const position = [0, 0, 0]
const rotation = [0, 0, 0, 1]
const scale = [1, 1, 1]
const color = [0, 0, 0, 1]

const translate = (x, y, z) => {
  position[0] = x
  position[1] = y
  position[2] = z
}

Object.assign(window, {
  controller,
  feedback,
  camera,
  sphere,
  world,
  plane,
  frame,
  vec3,
  box,
  ctx,
})

// swap targets every 10s following new target
window.target = sphere.position
let i = 0
setInterval(() => {
  target = i++ % 2 ? sphere.position : box.position
}, 10000)

frame(({time}) => {
  // vignette background effect
  const reduction = 2 - (0.5 + 0.5*Math.cos(time))
  color[0] = 0.025*time % 128
  color[1] = 0.025*time % 128
  color[2] = Math.sin(0.25*time) % 255
  background({reduction, color})

  // lerp into scene
  if (!mouse.wheel.deltaY) {
    vec3.lerp(camera.position, camera.position, [0, 0, 300], 0.0125)
  }

  // viewer
  const off = 20
  const d = 40
  let s = 0

  // lerp to target
  camera({target: vec3.lerp([], camera.target, target, 0.025)}, () => {
    // update controller state
    controller()

    // draw world
    world({rotation: quat.setAxisAngle([], [1, 0, 0], 0.05*time)}, ({model}) => {
      feedback({model})

      // draw plane in world
      plane()

      // orbit box around origin
      s = 2 + (0.5 - 0.5*Math.cos(time))
      translate(s + 300, s + 0.5, s + 10)
      vec3.transformQuat(
        position, position,
        quat.multiply(
          quat.setAxisAngle([], [1, 0, 0], 0.5*time),
          quat.setAxisAngle([], [0, 1, 0], 0.5*time),
          quat.setAxisAngle([], [0, 0, 1], 0.5*time))
      )

      // draw box with feedback
      s = off + (1.0 - 1.0*Math.cos(time))
      box({position}, ({model}) => {
        feedback({model, scale: [s, s, s]})
      })

      // oscillate sphere
      translate(s + (d - d*Math.sin(time)), s + (0.5 - 0.5*Math.cos(time)), 0)
      s = off + (0.5 - 0.5*Math.cos(time))
      // draw sphere with feedback
      sphere({position, color: [.5, .5, .25, 1]}, ({model}) => {
        feedback({model, scale: [s, s, s]})
      })
    })
  })
})
<|endoftext|>