<commit_before>/**
 * @namespace ajax
 * @summary module to make ajax requests
 */
var ajax = (function() {
    "use strict";

    /**
     * @memberof ajax
     * @summary executes the XMLHttpRequest
     * @private
     * @param c {object} request configuration hash
     */
    function sendRequest(c) {
        var req = new XMLHttpRequest();

        // start XMLHttpRequest
        req.open(c.method, c.url, c.async);
        setRequestHeaders(req, c.setHeaders);

        // request now going through
        req.onreadystatechange = function() {
            // Headers & status are received
            if (req.readyState === 2) {
                if (c.onHeaders) {
                    c.onHeaders(req.getAllResponseHeaders());
                }
            }

            // request is complete and successful
            if (req.readyState === 4) {
                // process success or failure callbacks
                if (req.status.toString().charAt(0) === "2" && c.onSuccess) {
                    c.onSuccess({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            return req.getResponseHeader.call(req, name);
                        }
                    });
                } else if (c.onFailure) {
                    c.onFailure({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            return req.getResponseHeader.call(req, name);
                        }
                    });
                }
            }
        };
        req.send(c.data);
    }

    /**
     * @memberof ajax
     * @summary sets basic headers for the request and sets the additional ones provided by the configuration
     * @private
     * @param req {object} XMLHttpRequest object
     * @param headers {object} additional headers to be injected
     */
    function setRequestHeaders(req, headers) {
        // set default values
        if (!headers["Content-Type"]) {
            headers["Content-Type"] = "application/json;charset=utf-8";
        }

        if (!headers.Accept) {
            headers.Accept = "application/json";
        }

        if (!headers["X-Requested-With"]) {
            headers["X-Requested-With"] = "XMLHttpRequest";
        }

        // get all object (t) keys from own properties
        // inject them as request headers
        Object.keys(headers).forEach(function(header) {
            req.setRequestHeader(header, headers[header]);
        });

        // xhr2 spec
        if (req.responseType) {
            req.responseType = c.responseType; // "arraybuffer", "blob", "document", "json", "text"
        }
    }

    /**
     * @memberof ajax
     * @summary parses the response data based on provided responseType
     * @private
     * @param req {object} XMLHttpRequest object
     * @param c {object} configuration hash
     * @returns the parsed data
     */
    function getResponse(req, c) {
        var r = req.response;

        if (c.responseType && c.responseType === "json" && r !== "") {
            r = JSON.parse(r);
        }

        return r;
    }

    /**
     * @memberof ajax
     * @private
     * @summary verifies content provided by configuration object
     * @param c {object} configuration hash
     * @returns {boolean} result of validation (true|false)
     */
    function validateConfig(c) {
        if (Object.prototype.toString.call(c.url) !== "[object String]") {
            throw new TypeError("ajax: requires a URL string");
        }

        if (Object.prototype.toString.call(c.method) === "[object String]") {
            c.method = c.method.toUpperCase();
            if (!["GET","POST","PUT","DELETE"].some(function(method) {
                return method === c.method;
            })) {
                throw new TypeError("ajax: 'method' must have one of the following values:\nGET\nPOST\nPUT\nDelete");
            }
        } else {
            throw Error("ajax: query 'method' is required");
        }

        if (c.setHeaders && Object.prototype.toString.call(c.setHeaders) !== "[object Object]") {
            throw new TypeError("ajax: 'setHeaders' is not an object");
        }

        if (c.onFailure && Object.prototype.toString.call(c.onFailure) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onSuccess && Object.prototype.toString.call(c.onSuccess) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onHeaders && Object.prototype.toString.call(c.onHeaders) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }

        if (c.responseType) {
            if (!["json","text","arraybuffer","document","blob"].some(function(value) {
                    return value === c.responseType;
                })) {
                throw new Error("ajax: responseType must have one of the following value:\njson\ntext\ndocument\nblob\narraybuffer");
            }
        }

        return true;
    }

    /**
     * @memberof ajax
     * @private
     * @summary builds the final request configuration object
     * @param c {object} configuration hash
     * @returns {
     *  {
     *   async: boolean,
     *   data: (object|null),
     *   setHeaders: (object|{}),
     *   method: string,
     *   onFailure: (function|null),
     *   onHeaders: (function|null),
     *   onSuccess: (function|null),
     *   responseType: (string),
     *   url: string,
     *   loaderTarget: (Element|null)
     *   }
     *  }
     */
    function finalizeConfig(c) {
        return {
            async: c.async !== false,
            data: c.data || null,
            setHeaders: c.setHeaders || {},
            method: c.method,
            onFailure: c.onFailure || null,
            onHeaders: c.onHeaders || null,
            onSuccess: c.onSuccess || null,
            responseType: c.responseType || "text",
            url: encodeURI(c.url).replace(/%5B/g, "[").replace(/%5D/g, "]")
        };
    }

    function query(c) {
        if (validateConfig(c)) {
            sendRequest(finalizeConfig(c));
        }
    }

    return query;
}());

// adding commonJS exports if module.exports is part of the env. otherwise expose as a global module.
if (typeof module !== undefined && typeof module.exports !== undefined) {
    module.exports = ajax;
} else {
    window.ajax = ajax;
}
<commit_msg>all requests are now ASYNC, since sync. requests are starting to be deprecated in many browsers<commit_after>/**
 * @namespace ajax
 * @summary module to make ajax requests
 */
var ajax = (function() {
    "use strict";

    /**
     * @memberof ajax
     * @summary executes the XMLHttpRequest
     * @private
     * @param c {object} request configuration hash
     */
    function sendRequest(c) {
        var req = new XMLHttpRequest();

        // start XMLHttpRequest
        req.open(c.method, c.url, true);
        setRequestHeaders(req, c.setHeaders);

        // request now going through
        req.onreadystatechange = function() {
            // Headers & status are received
            if (req.readyState === 2) {
                if (c.onHeaders) {
                    c.onHeaders(req.getAllResponseHeaders());
                }
            }

            // request is complete and successful
            if (req.readyState === 4) {
                // process success or failure callbacks
                if (req.status.toString().charAt(0) === "2" && c.onSuccess) {
                    c.onSuccess({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            return req.getResponseHeader.call(req, name);
                        }
                    });
                } else if (c.onFailure) {
                    c.onFailure({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            return req.getResponseHeader.call(req, name);
                        }
                    });
                }
            }
        };
        req.send(c.data);
    }

    /**
     * @memberof ajax
     * @summary sets basic headers for the request and sets the additional ones provided by the configuration
     * @private
     * @param req {object} XMLHttpRequest object
     * @param headers {object} additional headers to be injected
     */
    function setRequestHeaders(req, headers) {
        // set default values
        if (!headers["Content-Type"]) {
            headers["Content-Type"] = "application/json;charset=utf-8";
        }

        if (!headers.Accept) {
            headers.Accept = "application/json";
        }

        if (!headers["X-Requested-With"]) {
            headers["X-Requested-With"] = "XMLHttpRequest";
        }

        // get all object (t) keys from own properties
        // inject them as request headers
        Object.keys(headers).forEach(function(header) {
            req.setRequestHeader(header, headers[header]);
        });

        // xhr2 spec
        if (req.responseType) {
            req.responseType = c.responseType; // "arraybuffer", "blob", "document", "json", "text"
        }
    }

    /**
     * @memberof ajax
     * @summary parses the response data based on provided responseType
     * @private
     * @param req {object} XMLHttpRequest object
     * @param c {object} configuration hash
     * @returns the parsed data
     */
    function getResponse(req, c) {
        var r = req.response;

        if (c.responseType && c.responseType === "json" && r !== "") {
            r = JSON.parse(r);
        }

        return r;
    }

    /**
     * @memberof ajax
     * @private
     * @summary verifies content provided by configuration object, throws error on missing critical properties
     * @param c {object} configuration hash
     * @returns {boolean} result of validation (true|false)
     */
    function validateConfig(c) {
        if (Object.prototype.toString.call(c.url) !== "[object String]") {
            throw Error("ajax: requires a URL string");
        }

        if (Object.prototype.toString.call(c.method) === "[object String]") {
            c.method = c.method.toUpperCase();
            if (!["GET","POST","PUT","DELETE"].some(function(method) {
                return method === c.method;
            })) {
                throw new TypeError("ajax: 'method' must have one of the following values:\nGET\nPOST\nPUT\nDelete");
            }
        } else {
            throw Error("ajax: query 'method' is required");
        }

        if (c.setHeaders && Object.prototype.toString.call(c.setHeaders) !== "[object Object]") {
            throw new TypeError("ajax: 'setHeaders' is not an object");
        }

        if (c.onFailure && Object.prototype.toString.call(c.onFailure) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onSuccess && Object.prototype.toString.call(c.onSuccess) !== "[object Function]") {
            throw new TypeError("ajax: onSuccess must be a function");
        }
        if (c.onHeaders && Object.prototype.toString.call(c.onHeaders) !== "[object Function]") {
            throw new TypeError("ajax: onHeaders must be a function");
        }

        if (c.responseType) {
            if (!["json","text","arraybuffer","document","blob"].some(function(value) {
                    return value === c.responseType;
                })) {
                throw new Error("ajax: responseType must have one of the following value:\njson\ntext\ndocument\nblob\narraybuffer");
            }
        }

        return true;
    }

    /**
     * @memberof ajax
     * @private
     * @summary builds the final request configuration object
     * @param c {object} configuration hash
     * @returns {
     *  {
     *   async: boolean,
     *   data: (object|null),
     *   setHeaders: (object|{}),
     *   method: string,
     *   onFailure: (function|null),
     *   onHeaders: (function|null),
     *   onSuccess: (function|null),
     *   responseType: (string),
     *   url: string,
     *   loaderTarget: (Element|null)
     *   }
     *  }
     */
    function finalizeConfig(c) {
        return {
            data: c.data || null,
            setHeaders: c.setHeaders || {},
            method: c.method,
            onFailure: c.onFailure || null,
            onHeaders: c.onHeaders || null,
            onSuccess: c.onSuccess || null,
            responseType: c.responseType || "text",
            url: encodeURI(c.url).replace(/%5B/g, "[").replace(/%5D/g, "]")
        };
    }

    function query(c) {
        if (validateConfig(c)) {
            sendRequest(finalizeConfig(c));
        }
    }

    return query;
}());

// adding commonJS exports if module.exports is part of the env. otherwise expose as a global module.
if (typeof module !== undefined && typeof module.exports !== undefined) {
    module.exports = ajax;
} else {
    window.ajax = ajax;
}
<|endoftext|>


<commit_before><commit_msg>Fix SkinnedMuscle to handle setting  of color/material. fix comment regarding skin weights, and fix off-by-one loop<commit_after><|endoftext|>


<commit_before>
(function(FileBrowser) {

    // Private stuff

    // Public stuff
    FileBrowser.cfg.github = {
        uploadMethod = 'PUT';
        //TODO can this be moved up a level?
        fileName = '';
        mimeType = '';
        uploadUrl: function(row) {
            var deferred = $.Deferred();

            return $.ajax({
                type: 'POST',
                url: nodeApiUrl + '/s3/upload/',
                data: JSON.stringify({name: fileName, type:mimeType}),
                contentType: 'application/json',
                dataType: 'json'
            }).success(function (url) {
                deferred.resolve(url);
            });
        }

        uploadAdded: function(file, item) {
            fileName = file.name;
            mimeType = file.type;
        }
    };

})(FileBrowser);

/*
 *
 * xhr.setRequestHeader('Content-Type', type);
 * xhr.setRequestHeader('x-amz-acl', 'private');
 *
 *
 */
<commit_msg>Updated Hgrid config thanks @sloria<commit_after>
(function(FileBrowser) {

    // Private stuff

    // Public stuff
    FileBrowser.cfg.s3 = {
        uploadMethod = 'PUT';

        uploadAdded: function(file, item) {
            var deferred = $.Deferred();

            return $.ajax({
                type: 'POST',
                url: nodeApiUrl + '/s3/upload/',
                data: JSON.stringify({name: file.name, type: file.type}),
                contentType: 'application/json',
                dataType: 'json'
            }).success(function (url) {
                deferred.resolve(url);
            });
        }
    };

})(FileBrowser);

/*
 *
 * xhr.setRequestHeader('Content-Type', type);
 * xhr.setRequestHeader('x-amz-acl', 'private');
 *
 *
 */
<|endoftext|>


<commit_before>// @flow weak

const path = require('path');
const webpack = require('webpack');
const webpackBaseConfig = require('./webpackBaseConfig');
const dllManifest = require('./build/dll.manifest.json');
const BundleInspector = require('bundle-inspector-webpack-plugin');

module.exports = Object.assign({}, webpackBaseConfig, {
  cache: true,
  devtool: 'inline-source-map',
  context: path.resolve(__dirname),
  entry: {
    main: [
      'babel-polyfill', // polyfill for lesser browsers
      'eventsource-polyfill', // hot reloading in IE
      'react-hot-loader/patch',
      'webpack-dev-server/client?http://0.0.0.0:3000',
      'webpack/hot/only-dev-server',
      './src/index',
    ],
  },
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/build/',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          cacheDirectory: true,
        },
      },
      {
        test: /\.svg$/,
        loader: 'file-loader',
      },
      {
        test: /\.(jpg|gif|png)$/,
        loader: 'file-loader!img-loader',
      },
      {
        test: /\.md$/,
        loader: 'raw-loader',
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader',
      },
    ],
  },
  resolve: {
    alias: {
      docs: path.resolve(__dirname, '../docs'),
      resonance: path.resolve(__dirname, '../src'),
    },
  },
  plugins: webpackBaseConfig.plugins.concat([
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DllReferencePlugin({
      context: '.',
      manifest: dllManifest,
    }),
    new webpack.NamedModulesPlugin(),
    new BundleInspector(),
  ]),
});
<commit_msg>remove bundle inspector<commit_after>// @flow weak

const path = require('path');
const webpack = require('webpack');
const webpackBaseConfig = require('./webpackBaseConfig');
const dllManifest = require('./build/dll.manifest.json');

module.exports = Object.assign({}, webpackBaseConfig, {
  cache: true,
  devtool: 'inline-source-map',
  context: path.resolve(__dirname),
  entry: {
    main: [
      'babel-polyfill', // polyfill for lesser browsers
      'eventsource-polyfill', // hot reloading in IE
      'react-hot-loader/patch',
      'webpack-dev-server/client?http://0.0.0.0:3000',
      'webpack/hot/only-dev-server',
      './src/index',
    ],
  },
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/build/',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          cacheDirectory: true,
        },
      },
      {
        test: /\.svg$/,
        loader: 'file-loader',
      },
      {
        test: /\.(jpg|gif|png)$/,
        loader: 'file-loader!img-loader',
      },
      {
        test: /\.md$/,
        loader: 'raw-loader',
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader',
      },
    ],
  },
  resolve: {
    alias: {
      docs: path.resolve(__dirname, '../docs'),
      resonance: path.resolve(__dirname, '../src'),
    },
  },
  plugins: webpackBaseConfig.plugins.concat([
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DllReferencePlugin({
      context: '.',
      manifest: dllManifest,
    }),
    new webpack.NamedModulesPlugin(),
  ]),
});
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Charles du Jeu - Abstrium SAS <team (at) pyd.io>
 * This file is part of Pydio.
 *
 * Pydio is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Pydio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Pydio.  If not, see <http://www.gnu.org/licenses/>.
 *
 * The latest code can be found at <https://pydio.com>.
 */

class CustomIframe extends React.Component {

    onUnload(e) {
        let href = this.myIframe.contentDocument.location.href;

        if(href && href.indexOf('image=') > -1){
            this.save(href);
        }else if(href && (href.indexOf('close_pixlr')>-1 || href.indexOf('error_pixlr')>-1)){
            // TODO: Close the editor
        }
    }

    save(pixlrUrl) {
        const {pydio, node} = this.props;

        pydio.ApiClient.request({
            get_action: 'retrieve_pixlr_image',
            original_file: node.getPath(),
            new_url: pixlrUrl,
        }, function (transport) {
            node.getParent().getMetadata().set('preview_seed', Math.round(Math.random() * new Date().getTime()));
            pydio.fireNodeRefresh(node);
        });
    }

    componentDidMount() {
        this.myIframe.contentWindow.addEventListener("onbeforeunload", this.onUnload)
    }

    componentWillUnmount() {
        this.myIframe.contentWindow.removeEventListener("onbeforeunload", this.onUnload)
    }

    render() {
        return (
            <iframe
                ref={(element) => {this.myIframe = element}}
                src={this.props.url}
                style={{...this.props.style, border: 0, flex: 1}}
                className="vertical_fit"
                onLoad={this.onUnload.bind(this)}
            >
            </iframe>
        );
    }
}

class Editor extends React.Component {

    componentDidMount() {
        this.loadNode(this.props)
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.node !== this.props.node) {
            this.loadNode(nextProps)
        }
    }

    loadNode(props) {
        const {pydio, node} = props;

        this.setState({url: pydio.Parameters.get('ajxpServerAccess')+"&get_action=post_to_server&file=base64encoded:" + HasherUtils.base64_encode(node.getPath()) + "&parent_url=" + HasherUtils.base64_encode(DOMUtils.getUrlFromBase())});
    }

    render() {
        if(!this.state){
            return null;
        }
        return (
            <CustomIframe
                {...this.props}
                url={this.state.url}
            />
        );
    }
}

export default Editor
<commit_msg>Catch iFrame errors<commit_after>/*
 * Copyright 2007-2017 Charles du Jeu - Abstrium SAS <team (at) pyd.io>
 * This file is part of Pydio.
 *
 * Pydio is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Pydio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Pydio.  If not, see <http://www.gnu.org/licenses/>.
 *
 * The latest code can be found at <https://pydio.com>.
 */

class CustomIframe extends React.Component {

    onUnload(e) {
        try{
            let href = this.myIframe.contentDocument.location.href;

            if(href && href.indexOf('image=') > -1){
                this.save(href);
            }else if(href && (href.indexOf('close_pixlr')>-1 || href.indexOf('error_pixlr')>-1)){
                // TODO: Close the editor
            }
        }catch(e){}
    }

    save(pixlrUrl) {
        const {pydio, node} = this.props;

        pydio.ApiClient.request({
            get_action: 'retrieve_pixlr_image',
            original_file: node.getPath(),
            new_url: pixlrUrl,
        }, function (transport) {
            node.getParent().getMetadata().set('preview_seed', Math.round(Math.random() * new Date().getTime()));
            pydio.fireNodeRefresh(node);
        });
    }

    componentDidMount() {
        try{
            this.myIframe.contentWindow.addEventListener("onbeforeunload", this.onUnload)
        }catch(e){}
    }

    componentWillUnmount() {
        try{
            this.myIframe.contentWindow.removeEventListener("onbeforeunload", this.onUnload)
        }catch(e){}
    }

    render() {
        return (
            <iframe
                ref={(element) => {this.myIframe = element}}
                src={this.props.url}
                style={{...this.props.style, border: 0, flex: 1}}
                className="vertical_fit"
                onLoad={this.onUnload.bind(this)}
            >
            </iframe>
        );
    }
}

class Editor extends React.Component {

    componentDidMount() {
        this.loadNode(this.props)
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.node !== this.props.node) {
            this.loadNode(nextProps)
        }
    }

    loadNode(props) {
        const {pydio, node} = props;

        this.setState({url: pydio.Parameters.get('ajxpServerAccess')+"&get_action=post_to_server&file=base64encoded:" + HasherUtils.base64_encode(node.getPath()) + "&parent_url=" + HasherUtils.base64_encode(DOMUtils.getUrlFromBase())});
    }

    render() {
        if(!this.state){
            return null;
        }
        return (
            <CustomIframe
                {...this.props}
                url={this.state.url}
            />
        );
    }
}

export default Editor
<|endoftext|>


<commit_before>'use strict';
import { _ } from 'meteor/underscore';
import { $ } from 'meteor/jquery';
import { Template } from 'meteor/templating';
import { dbVariables } from '../../db/dbVariables';

Template.pagination.helpers({
  haveData() {
    const totalCount = dbVariables.get(this.useVariableForTotalCount);

    return totalCount > this.dataNumberPerPage;
  },
  pages() {
    const totalCount = dbVariables.get(this.useVariableForTotalCount);
    const totalPages = Math.ceil(totalCount / this.dataNumberPerPage);
    if (totalPages <= 7) {
      return _.range(1, totalPages + 1);
    }
    else {
      const offset = this.offset.get();
      const currentPage = (offset / this.dataNumberPerPage) + 1;
      if (currentPage - 3 >= 1 && currentPage + 3 <= totalPages) {
        return _.range(currentPage - 3, currentPage + 4);
      }
      else if (currentPage - 3 < 1) {
        return _.range(1, 8);
      }
      else if (currentPage + 3 > totalPages) {
        return _.range(totalPages - 6, totalPages + 1);
      }
    }
  },
  pageItemClass(page) {
    const offset = this.offset.get();
    const currentPage = (offset / this.dataNumberPerPage) + 1;

    return (page === currentPage) ? 'page-item active' : 'page-item';
  },
  pageLinkHref(page) {
    const templateInstance = Template.instance();
    const data = templateInstance.data;
    const totalCount = dbVariables.get(data.useVariableForTotalCount);
    const totalPages = Math.ceil(totalCount / data.dataNumberPerPage);

    if (page === 'end') {
      return './' + totalPages;
    }

    const offset = this.offset.get();
    const currentPage = (offset / this.dataNumberPerPage) + 1;
    if (page === 'prev') {
      return './' + Math.max(1, currentPage-1);
    }
    if (page === 'next') {
      return './' + Math.min(totalPages, currentPage+1);
    }

    return './' + page;
  }
});
Template.pagination.events({
  'click a[href]'(event, templateInstance) {
    const data = templateInstance.data;
    if (! data.useHrefRoute) {
      event.preventDefault();
      const href = $(event.currentTarget).attr('href');
      const toPage = parseInt(href.slice(2), 10);
      const newOffset = (toPage - 1) * data.dataNumberPerPage;
      data.offset.set(newOffset);
    }
  }
});
<commit_msg>eslint<commit_after>'use strict';
import { _ } from 'meteor/underscore';
import { $ } from 'meteor/jquery';
import { Template } from 'meteor/templating';
import { dbVariables } from '../../db/dbVariables';

Template.pagination.helpers({
  haveData() {
    const totalCount = dbVariables.get(this.useVariableForTotalCount);

    return totalCount > this.dataNumberPerPage;
  },
  pages() {
    const totalCount = dbVariables.get(this.useVariableForTotalCount);
    const totalPages = Math.ceil(totalCount / this.dataNumberPerPage);
    if (totalPages <= 7) {
      return _.range(1, totalPages + 1);
    }
    else {
      const offset = this.offset.get();
      const currentPage = (offset / this.dataNumberPerPage) + 1;
      if (currentPage - 3 >= 1 && currentPage + 3 <= totalPages) {
        return _.range(currentPage - 3, currentPage + 4);
      }
      else if (currentPage - 3 < 1) {
        return _.range(1, 8);
      }
      else if (currentPage + 3 > totalPages) {
        return _.range(totalPages - 6, totalPages + 1);
      }
    }
  },
  pageItemClass(page) {
    const offset = this.offset.get();
    const currentPage = (offset / this.dataNumberPerPage) + 1;

    return (page === currentPage) ? 'page-item active' : 'page-item';
  },
  pageLinkHref(page) {
    const templateInstance = Template.instance();
    const data = templateInstance.data;
    const totalCount = dbVariables.get(data.useVariableForTotalCount);
    const totalPages = Math.ceil(totalCount / data.dataNumberPerPage);

    if (page === 'end') {
      return './' + totalPages;
    }

    const offset = this.offset.get();
    const currentPage = (offset / this.dataNumberPerPage) + 1;
    if (page === 'prev') {
      return './' + Math.max(1, currentPage - 1);
    }
    if (page === 'next') {
      return './' + Math.min(totalPages, currentPage + 1);
    }

    return './' + page;
  }
});
Template.pagination.events({
  'click a[href]'(event, templateInstance) {
    const data = templateInstance.data;
    if (! data.useHrefRoute) {
      event.preventDefault();
      const href = $(event.currentTarget).attr('href');
      const toPage = parseInt(href.slice(2), 10);
      const newOffset = (toPage - 1) * data.dataNumberPerPage;
      data.offset.set(newOffset);
    }
  }
});
<|endoftext|>


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

var $ =  {
  hubConnection: createMockHubObject
};

function createMockHubObject () {
  'use strict';

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

  return hub;
}

function HubProxy ( hubName ) {
  'use strict';

  this._listeners = {};

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

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

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

var $ =  {
  hubConnection: createMockHubObject
};

function createMockHubObject () {
  'use strict';

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

  return hub;
}

function HubProxy ( hubName ) {
  'use strict';

  this._listeners = {};

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

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

<|endoftext|>


<commit_before>'use strict';

var famous = require('famous');
var Consts = require('./Consts.js');

var Node = famous.core.Node;
var Position = famous.components.Position;
var DOMElement = famous.domRenderables.DOMElement;

function Dot(id) {
	Node.call(this);

	// Center dot.
	this
		.setMountPoint(0.5, 0.5, 0)
		.setAlign(0.5, 0.5, 0)
		.setSizeMode('absolute', 'absolute', 'absolute')
		.setAbsoluteSize(Consts.DOT_SIZE, Consts.DOT_SIZE, Consts.DOT_SIZE);

	this.domElement = new DOMElement(this, {
		properties: {
			background: Consts.DOT_COLOR__UNTOUCHED
		},
		classes: ['Dot']
	});

	this.id = id;
	this.state = Consts.DOT_STATE__UNTOUCHED;

	this.hover = function hover() {
		if (this.state === Consts.DOT_STATE__UNTOUCHED) {
			this.state = Consts.DOT_STATE__HOVERED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__HOVERED);
		}
	};

	this.unhover = function unhover() {
		if (this.state === Consts.DOT_STATE__HOVERED) {
			this.state = Consts.DOT_STATE__UNTOUCHED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__UNTOUCHED);
		}
	};

	this.place = function place() {
		if (this.state === Consts.DOT_STATE__HOVERED) {
			this.state = Consts.DOT_STATE__PLACED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__PLACED);
		}
	};

	this.unplace = function unplace() {
		if (this.state === Consts.DOT_STATE__PLACED) {
			this.state = Consts.DOT_STATE__UNTOUCHED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__UNTOUCHED);
		}
	};

	this.position = new Position(this);

	this.addUIEvent('mousedown');
	this.addUIEvent('mousemove');
	this.addUIEvent('click');
	this.addUIEvent('mouseup');
}

Dot.prototype = Object.create(Node.prototype);
Dot.prototype.constructor = Dot;

/*jshint -W074 */
Dot.prototype.onReceive = function onReceive(type, ev) {
	switch (type) {
	case 'mousedown':
			this._parent.mousingDown(this.id);
			break;
	case 'mousemove':
			if (this._parent.mousing === true) {
				this._parent.stateDot(this.id);
				this.emit('id', this.domElement.id).emit('state', this.domElement.state);
			}
			break;
	case 'click':
			this._parent.stateDot(this.id);
			this.emit('id', this.domElement.id).emit('state', this.domElement.state);
			break;
	case 'mouseup':
			this._parent.mousingUp(this.id);
			break;
	default:
			return false;
	}
};/*jshint +W074 */

module.exports = Dot;
<commit_msg>Added setTimeout to Dot for unplace()<commit_after>'use strict';

var famous = require('famous');
var Consts = require('./Consts.js');

var FamousEngine = famous.core.FamousEngine;
var Node = famous.core.Node;
var Position = famous.components.Position;
var DOMElement = famous.domRenderables.DOMElement;

function Dot(id) {
	Node.call(this);

	// Center dot.
	this
		.setMountPoint(0.5, 0.5, 0)
		.setAlign(0.5, 0.5, 0)
		.setSizeMode('absolute', 'absolute', 'absolute')
		.setAbsoluteSize(Consts.DOT_SIZE, Consts.DOT_SIZE, Consts.DOT_SIZE);

	this.domElement = new DOMElement(this, {
		properties: {
			background: Consts.DOT_COLOR__UNTOUCHED
		},
		classes: ['Dot']
	});

	this.id = id;
	this.state = Consts.DOT_STATE__UNTOUCHED;

	this.hover = function hover() {
		if (this.state === Consts.DOT_STATE__UNTOUCHED) {
			this.state = Consts.DOT_STATE__HOVERED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__HOVERED);
		}
	};

	this.unhover = function unhover() {
		if (this.state === Consts.DOT_STATE__HOVERED) {
			this.state = Consts.DOT_STATE__UNTOUCHED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__UNTOUCHED);
		}
	};

	this.place = function place() {
		if (this.state === Consts.DOT_STATE__HOVERED) {
			this.state = Consts.DOT_STATE__PLACED;
			this.domElement.setProperty('background-color', Consts.DOT_COLOR__PLACED);
		}
	};

	this.unplace = function unplace(delay) {
		var delay = delay || false;
		var self = this;
		if (this.state === Consts.DOT_STATE__PLACED) {
			if (delay) {
				var clock = FamousEngine.getClock();
				clock.setTimeout(function() {
					self.state = Consts.DOT_STATE__UNTOUCHED;
					self.domElement.setProperty('background-color', Consts.DOT_COLOR__UNTOUCHED);
				}, Consts.DURATION);
			} else {
				this.state = Consts.DOT_STATE__UNTOUCHED;
				this.domElement.setProperty('background-color', Consts.DOT_COLOR__UNTOUCHED);
			}
		}
	};

	this.position = new Position(this);

	this.addUIEvent('mousedown');
	this.addUIEvent('mousemove');
	this.addUIEvent('click');
	this.addUIEvent('mouseup');
}

Dot.prototype = Object.create(Node.prototype);
Dot.prototype.constructor = Dot;

/*jshint -W074 */
Dot.prototype.onReceive = function onReceive(type, ev) {
	switch (type) {
	case 'mousedown':
			this._parent.mousingDown(this.id);
			break;
	case 'mousemove':
			if (this._parent.mousing === true) {
				this._parent.stateDot(this.id);
				this.emit('id', this.domElement.id).emit('state', this.domElement.state);
			}
			break;
	case 'click':
			this._parent.stateDot(this.id);
			this.emit('id', this.domElement.id).emit('state', this.domElement.state);
			break;
	case 'mouseup':
			this._parent.mousingUp(this.id);
			break;
	default:
			return false;
	}
};/*jshint +W074 */

module.exports = Dot;
<|endoftext|>


<commit_before>"use strict";

const path   = require('path');
const fs     = require('fs');
const semver = require('semver');
const webpack = require('webpack');

var plugins = require('webpack-load-plugins')();

const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), {encoding: 'utf8'}));

function getLicense(pkg) {
  return `@license twgl.js ${pkg.version} Copyright (c) 2015, Gregg Tavares All Rights Reserved.
Available via the MIT license.
see: http://github.com/greggman/twgl.js for details`;
}

var replaceHandlers = {};
function registerReplaceHandler(keyword, handler) {
  replaceHandlers[keyword] = handler;
}

/**
 * Replace %(id)s in strings with values in objects(s)
 *
 * Given a string like `"Hello %(name)s from %(user.country)s"`
 * and an object like `{name:"Joe",user:{country:"USA"}}` would
 * return `"Hello Joe from USA"`.
 *
 * @param {string} str string to do replacements in
 * @param {Object|Object[]} params one or more objects.
 * @returns {string} string with replaced parts
 */
var replaceParams = (function() {
  var replaceParamsRE = /%\(([^\)]+)\)s/g;

  return function(str, params) {
    if (!params.length) {
      params = [params];
    }

    return str.replace(replaceParamsRE, function(match, key) {
      var colonNdx = key.indexOf(":");
      if (colonNdx >= 0) {
        try {
          var args = hanson.parse("{" + key + "}");
          var handlerName = Object.keys(args)[0];
          var handler = replaceHandlers[handlerName];
          if (handler) {
            return handler(args[handlerName]);
          }
          console.error("unknown substition handler: " + handlerName);
        } catch (e) {
          console.error(e);
          console.error("bad substitution: %(" + key + ")s");
        }
      } else {
        // handle normal substitutions.
        var keys = key.split('.');
        for (var ii = 0; ii < params.length; ++ii) {
          var obj = params[ii];
          for (var jj = 0; jj < keys.length; ++jj) {
            var key = keys[jj];
            obj = obj[key];
            if (obj === undefined) {
              break;
            }
          }
          if (obj !== undefined) {
            return obj;
          }
        }
      }
      console.error("unknown key: " + key);
      return "%(" + key + ")s";
    });
  };
}());

module.exports = function(grunt) {

  require('load-grunt-tasks')(grunt);

  var srcFiles = [
    'src/twgl.js',
    'src/attributes.js',
    'src/draw.js',
    'src/framebuffers.js',
    'src/programs.js',
    'src/textures.js',
    'src/typedarrays.js',
    'src/vertex-arrays.js',
  ];

  var thirdPartyFiles = [
  ];

  var extraFiles = [
    'src/v3.js',
    'src/m4.js',
    'src/primitives.js',
  ];

  var docsFiles = srcFiles.concat(extraFiles, 'README.md');
  var libFiles = srcFiles.concat(thirdPartyFiles);
  var fullLibFiles = [].concat(srcFiles, extraFiles, thirdPartyFiles);

  grunt.initConfig({
    jsdoc: {
      docs: {
        src: docsFiles,
        options: {
          destination: 'docs',
          configure: 'build/jsdoc.conf.json',
//          template: 'build/jsdoc-template/template',
          template: './node_modules/minami',
          outputSourceFiles: false,
        },
      },
    },
    webpack: {
      full: {
        entry: './src/twgl-full.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl-full.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
      base: {
        entry: './src/twgl-base.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
      fullMin: {
        entry: './src/twgl-full.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
          new webpack.optimize.UglifyJsPlugin({
            compress: {
              warnings: false,
            },
            mangle: true,
            //mangle: {
            //  props: {
            //    ignore_quoted: true,
            //    regex: /^((?!(createElement|getContext)).)*$/,
            //  },
            //},
          }),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl-full.min.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
      baseMin: {
        entry: './src/twgl-base.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
          new webpack.optimize.UglifyJsPlugin({
            compress: {
              warnings: false,
            },
            mangle: true,
          }),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl.min.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
    },
    eslint: {
      lib: {
        src: [
          'src/*',
        ],
        options: {
          configFile: 'build/conf/eslint.json',
          //rulesdir: ['build/rules'],
        },
      },
      examples: {
        src: [
          'resources/js',
          'examples/*.html',
          'examples/js',
        ],
        options: {
          configFile: 'build/conf/eslint-docs.json',
          //rulesdir: ['build/rules'],
        },
      },
    },
    copy: {
      twgl: {
        src: 'dist/2.x/twgl.js',
        dest: 'npm/base/dist/2.x/twgl.js',
      },
      readme: {
        src: 'README.md',
        dest: 'npm/base/README.md',
      },
    },
    browserify: {
      example: {
        files: {
          'examples/js/browserified-example.js': ['examples/js/browserify-example.js'],
        },
      },
    },
    clean: {
      dist: [ 'dist/2.x' ],
      docs: [ 'docs' ],
    },
  });

  grunt.registerTask('makeindex', function() {
    var marked  = require('marked');
    var fs      = require('fs');
    marked.setOptions({ rawHtml: true });
    var html = marked(fs.readFileSync('README.md', {encoding: 'utf8'}));
    var template = fs.readFileSync('build/templates/index.template', {encoding: 'utf8'});
    var content = replaceParams(template, {
      content: html,
      license: getLicense(pkg),
      srcFileName: 'README.md',
      title: 'TWGL.js, a tiny WebGL helper library',
      version: pkg.version,
    });
    content = content.replace(/href="http\:\/\/twgljs.org\//g, 'href="/');
    fs.writeFileSync('index.html', content);
  });

  function getHeaderVersion(filename) {
    var twglVersionRE = / (\d+\.\d+\.\d+) /;
    return twglVersionRE.exec(fs.readFileSync(filename, {encoding: "utf8"}))[1];
  }

  function getPackageVersion(filename) {
    return JSON.parse(fs.readFileSync(filename, {encoding: "utf8"})).version;
  }

  function bump(type) {
    pkg.version = semver.inc(pkg.version, type);
    fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2));
    var filename = "bower.json";
    var p = JSON.parse(fs.readFileSync(filename, {encoding: "utf8"}));
    p.version = pkg.version;
    fs.writeFileSync(filename, JSON.stringify(p, null, 2));
    grunt.config.set('webpack.full.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
    grunt.config.set('webpack.base.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
    grunt.config.set('webpack.fullMin.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
    grunt.config.set('webpack.baseMin.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
  }

  grunt.registerTask('bumppatchimpl', function() { bump('patch'); });
  grunt.registerTask('bumpminorimpl', function() { bump('minor'); });
  grunt.registerTask('bumpmajorimpl', function() { bump('major'); });

  grunt.registerTask('versioncheck', function() {
    var fs = require('fs');
    var good = true;
    [
      { filename: 'dist/2.x/twgl.js',          fn: getHeaderVersion, },
      { filename: 'dist/2.x/twgl-full.js',     fn: getHeaderVersion, },
      { filename: 'dist/2.x/twgl.min.js',      fn: getHeaderVersion, },
      { filename: 'dist/2.x/twgl-full.min.js', fn: getHeaderVersion, },
      { filename: 'package.json',          fn: getPackageVersion, },
    ].forEach(function(file) {
      var version = file.fn(file.filename);
      if (version !== pkg.version) {
        good = false;
        grunt.log.error("version mis-match in:", file.filename, " Expected:", pkg.version, " Actual:", version);
      }
    });
    return good;
  });

  grunt.registerTask('npmpackage', function() {
    var p = JSON.parse(fs.readFileSync('package.json', {encoding: "utf8"}));
    p.name = "twgl-base.js";
    p.scripts = {};
    p.devDependencies = {};
    p.main = "dist/2.x/twgl.js";
    p.files = [ 'dist/2.x/twgl.js' ];
    fs.writeFileSync("npm/base/package.json", JSON.stringify(p, null, 2), {encoding: "utf8"});
  });

  grunt.registerTask('docs', [
      'eslint:examples',
      'clean:docs',
      'jsdoc',
      'makeindex',
  ]);
  grunt.registerTask('build', [
      'eslint:lib',
      'clean:dist',
      'webpack',
      'copy',
      'npmpackage',
  ]);
  grunt.registerTask('bumppatch', [
      'eslint:lib',
      'eslint:examples',
      'bumppatchimpl',
      'build',
      'browserify',
      'docs',
  ]);
  grunt.registerTask('bumpminor', [
      'eslint:lib',
      'eslint:examples',
      'bumpminorimpl',
      'build',
      'browserify',
      'docs',
  ]);
  grunt.registerTask('bumpmajor', [
      'eslint:lib',
      'eslint:examples',
      'bumpmajorimpl',
      'build',
      'browserify',
      'docs',
  ]);
  grunt.registerTask('default', 'build');
};

<commit_msg>add property mangling to build<commit_after>"use strict";

const path   = require('path');
const fs     = require('fs');
const semver = require('semver');
const webpack = require('webpack');

var plugins = require('webpack-load-plugins')();

const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), {encoding: 'utf8'}));

function getLicense(pkg) {
  return `@license twgl.js ${pkg.version} Copyright (c) 2015, Gregg Tavares All Rights Reserved.
Available via the MIT license.
see: http://github.com/greggman/twgl.js for details`;
}

var replaceHandlers = {};
function registerReplaceHandler(keyword, handler) {
  replaceHandlers[keyword] = handler;
}

/**
 * Replace %(id)s in strings with values in objects(s)
 *
 * Given a string like `"Hello %(name)s from %(user.country)s"`
 * and an object like `{name:"Joe",user:{country:"USA"}}` would
 * return `"Hello Joe from USA"`.
 *
 * @param {string} str string to do replacements in
 * @param {Object|Object[]} params one or more objects.
 * @returns {string} string with replaced parts
 */
var replaceParams = (function() {
  var replaceParamsRE = /%\(([^\)]+)\)s/g;

  return function(str, params) {
    if (!params.length) {
      params = [params];
    }

    return str.replace(replaceParamsRE, function(match, key) {
      var colonNdx = key.indexOf(":");
      if (colonNdx >= 0) {
        try {
          var args = hanson.parse("{" + key + "}");
          var handlerName = Object.keys(args)[0];
          var handler = replaceHandlers[handlerName];
          if (handler) {
            return handler(args[handlerName]);
          }
          console.error("unknown substition handler: " + handlerName);
        } catch (e) {
          console.error(e);
          console.error("bad substitution: %(" + key + ")s");
        }
      } else {
        // handle normal substitutions.
        var keys = key.split('.');
        for (var ii = 0; ii < params.length; ++ii) {
          var obj = params[ii];
          for (var jj = 0; jj < keys.length; ++jj) {
            var key = keys[jj];
            obj = obj[key];
            if (obj === undefined) {
              break;
            }
          }
          if (obj !== undefined) {
            return obj;
          }
        }
      }
      console.error("unknown key: " + key);
      return "%(" + key + ")s";
    });
  };
}());

module.exports = function(grunt) {

  require('load-grunt-tasks')(grunt);

  var srcFiles = [
    'src/twgl.js',
    'src/attributes.js',
    'src/draw.js',
    'src/framebuffers.js',
    'src/programs.js',
    'src/textures.js',
    'src/typedarrays.js',
    'src/vertex-arrays.js',
  ];

  var thirdPartyFiles = [
  ];

  var extraFiles = [
    'src/v3.js',
    'src/m4.js',
    'src/primitives.js',
  ];

  var docsFiles = srcFiles.concat(extraFiles, 'README.md');
  var libFiles = srcFiles.concat(thirdPartyFiles);
  var fullLibFiles = [].concat(srcFiles, extraFiles, thirdPartyFiles);

  grunt.initConfig({
    jsdoc: {
      docs: {
        src: docsFiles,
        options: {
          destination: 'docs',
          configure: 'build/jsdoc.conf.json',
//          template: 'build/jsdoc-template/template',
          template: './node_modules/minami',
          outputSourceFiles: false,
        },
      },
    },
    webpack: {
      full: {
        entry: './src/twgl-full.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl-full.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
      base: {
        entry: './src/twgl-base.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
      fullMin: {
        entry: './src/twgl-full.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
          new webpack.optimize.UglifyJsPlugin({
            compress: {
              warnings: false,
            },
            //mangle: true,
            mangle: {
              props: {
                ignore_quoted: true,
                //regex: /^((?!(createElement|getContext)).)*$/,
                regex: /^(colorRenderable|textureFilterable|bytesPerElement|numColorComponents|textureFormat)$/,
              },
            },
          }),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl-full.min.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
      baseMin: {
        entry: './src/twgl-base.js',
        plugins: [
          new webpack.BannerPlugin(getLicense(pkg)),
          new webpack.optimize.UglifyJsPlugin({
            compress: {
              warnings: false,
            },
            //mangle: true,
            mangle: {
              props: {
                ignore_quoted: true,
                //regex: /^((?!(createElement|getContext)).)*$/,
                regex: /^(colorRenderable|textureFilterable|bytesPerElement|numColorComponents|textureFormat)$/,
              },
            },
          }),
        ],
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              query: {
                presets: ['stage-0', 'es2015'],
              },
            },
          ],
        },
        output: {
          path: path.join(__dirname, 'dist/2.x'),
          filename: 'twgl.min.js',
          library: 'twgl',
          libraryTarget: 'umd',
        },
      },
    },
    eslint: {
      lib: {
        src: [
          'src/*',
        ],
        options: {
          configFile: 'build/conf/eslint.json',
          //rulesdir: ['build/rules'],
        },
      },
      examples: {
        src: [
          'resources/js',
          'examples/*.html',
          'examples/js',
        ],
        options: {
          configFile: 'build/conf/eslint-docs.json',
          //rulesdir: ['build/rules'],
        },
      },
    },
    copy: {
      twgl: {
        src: 'dist/2.x/twgl.js',
        dest: 'npm/base/dist/2.x/twgl.js',
      },
      readme: {
        src: 'README.md',
        dest: 'npm/base/README.md',
      },
    },
    browserify: {
      example: {
        files: {
          'examples/js/browserified-example.js': ['examples/js/browserify-example.js'],
        },
      },
    },
    clean: {
      dist: [ 'dist/2.x' ],
      docs: [ 'docs' ],
    },
  });

  grunt.registerTask('makeindex', function() {
    var marked  = require('marked');
    var fs      = require('fs');
    marked.setOptions({ rawHtml: true });
    var html = marked(fs.readFileSync('README.md', {encoding: 'utf8'}));
    var template = fs.readFileSync('build/templates/index.template', {encoding: 'utf8'});
    var content = replaceParams(template, {
      content: html,
      license: getLicense(pkg),
      srcFileName: 'README.md',
      title: 'TWGL.js, a tiny WebGL helper library',
      version: pkg.version,
    });
    content = content.replace(/href="http\:\/\/twgljs.org\//g, 'href="/');
    fs.writeFileSync('index.html', content);
  });

  function getHeaderVersion(filename) {
    var twglVersionRE = / (\d+\.\d+\.\d+) /;
    return twglVersionRE.exec(fs.readFileSync(filename, {encoding: "utf8"}))[1];
  }

  function getPackageVersion(filename) {
    return JSON.parse(fs.readFileSync(filename, {encoding: "utf8"})).version;
  }

  function bump(type) {
    pkg.version = semver.inc(pkg.version, type);
    fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2));
    var filename = "bower.json";
    var p = JSON.parse(fs.readFileSync(filename, {encoding: "utf8"}));
    p.version = pkg.version;
    fs.writeFileSync(filename, JSON.stringify(p, null, 2));
    grunt.config.set('webpack.full.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
    grunt.config.set('webpack.base.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
    grunt.config.set('webpack.fullMin.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
    grunt.config.set('webpack.baseMin.plugins.0', new webpack.BannerPlugin(getLicense(pkg)));
  }

  grunt.registerTask('bumppatchimpl', function() { bump('patch'); });
  grunt.registerTask('bumpminorimpl', function() { bump('minor'); });
  grunt.registerTask('bumpmajorimpl', function() { bump('major'); });

  grunt.registerTask('versioncheck', function() {
    var fs = require('fs');
    var good = true;
    [
      { filename: 'dist/2.x/twgl.js',          fn: getHeaderVersion, },
      { filename: 'dist/2.x/twgl-full.js',     fn: getHeaderVersion, },
      { filename: 'dist/2.x/twgl.min.js',      fn: getHeaderVersion, },
      { filename: 'dist/2.x/twgl-full.min.js', fn: getHeaderVersion, },
      { filename: 'package.json',          fn: getPackageVersion, },
    ].forEach(function(file) {
      var version = file.fn(file.filename);
      if (version !== pkg.version) {
        good = false;
        grunt.log.error("version mis-match in:", file.filename, " Expected:", pkg.version, " Actual:", version);
      }
    });
    return good;
  });

  grunt.registerTask('npmpackage', function() {
    var p = JSON.parse(fs.readFileSync('package.json', {encoding: "utf8"}));
    p.name = "twgl-base.js";
    p.scripts = {};
    p.devDependencies = {};
    p.main = "dist/2.x/twgl.js";
    p.files = [ 'dist/2.x/twgl.js' ];
    fs.writeFileSync("npm/base/package.json", JSON.stringify(p, null, 2), {encoding: "utf8"});
  });

  grunt.registerTask('docs', [
      'eslint:examples',
      'clean:docs',
      'jsdoc',
      'makeindex',
  ]);
  grunt.registerTask('build', [
      'eslint:lib',
      'clean:dist',
      'webpack',
      'copy',
      'npmpackage',
  ]);
  grunt.registerTask('bumppatch', [
      'eslint:lib',
      'eslint:examples',
      'bumppatchimpl',
      'build',
      'browserify',
      'docs',
  ]);
  grunt.registerTask('bumpminor', [
      'eslint:lib',
      'eslint:examples',
      'bumpminorimpl',
      'build',
      'browserify',
      'docs',
  ]);
  grunt.registerTask('bumpmajor', [
      'eslint:lib',
      'eslint:examples',
      'bumpmajorimpl',
      'build',
      'browserify',
      'docs',
  ]);
  grunt.registerTask('default', 'build');
};

<|endoftext|>


<commit_before>import http from 'http';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import { makeExecutableSchema } from 'graphql-tools';
import { graphqlExpress } from 'apollo-server-express';
import graphqlPlayground from 'graphql-playground-middleware-express';
import checkEnv from 'check-env';
import { graphqlSchema, graphqlResolvers } from './graphql';
import config from './constants/config';

checkEnv(['encryption_key']);

const app = express();
app.server = http.createServer(app);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

const executableSchema = makeExecutableSchema({
  typeDefs: [graphqlSchema],
  resolvers: graphqlResolvers,
});

app.use(
  '/graphql',
  bodyParser.json(),
  graphqlExpress({
    schema: executableSchema,
    formatError: error => ({
      message: 'Internal Server Error',
      path: error.path,
    }),
    tracing: true,
  }),
);

app.get('/playground', graphqlPlayground({ endpoint: '/graphql' }));

app.get('/', (req, res) => res.redirect('/playground'));

app.server.listen(process.env.PORT || config.server.port);
// eslint-disable-next-line no-console
console.log(`🚀  Server listening on port ${app.server.address().port}...`);
<commit_msg>:bug: Fix `port of undefined` error<commit_after>import http from 'http';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import { makeExecutableSchema } from 'graphql-tools';
import { graphqlExpress } from 'apollo-server-express';
import graphqlPlayground from 'graphql-playground-middleware-express';
import checkEnv from 'check-env';
import { graphqlSchema, graphqlResolvers } from './graphql';
import config from './constants/config';

checkEnv(['encryption_key']);

const PORT = process.env.PORT || config.server.port;

const app = express();
app.server = http.createServer(app);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

const executableSchema = makeExecutableSchema({
  typeDefs: [graphqlSchema],
  resolvers: graphqlResolvers,
});

app.use(
  '/graphql',
  bodyParser.json(),
  graphqlExpress({
    schema: executableSchema,
    formatError: error => ({
      message: 'Internal Server Error',
      path: error.path,
    }),
    tracing: true,
  }),
);

app.get('/playground', graphqlPlayground({ endpoint: '/graphql' }));

app.get('/', (req, res) => res.redirect('/playground'));

app.server.listen(PORT);
// eslint-disable-next-line no-console
console.log(`🚀  Server listening on port ${PORT}...`);
<|endoftext|>


<commit_before>var gulp = require('gulp');
var del = require('del');
var gulp_less = require('gulp-less');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var coffee = require("gulp-coffee");
var ngAnnotate = require('gulp-ng-annotate');
var gutil = require('gulp-util');
var rev = require('gulp-rev');
var manifest = require('gulp-rev-rails-manifest');
var gulpif = require('gulp-if');
var SprocketsChain = require("sprockets-chain");
var dev = (process.env.NODE_ENV == 'development' || process.env.NODE_ENV == 'dev')

var isCoffee = function(file) {
  return file.path.indexOf(".coffee") > -1
}

var isLess = function(file) {
  return file.path.indexOf(".less") > -1
}

var needsMinify = function(file) {
  return file.path.indexOf(".min") < 0
}

gulp.task('clean', function(cb) {
  del([
    'public/assets/build/*',
    'public/assets/*.css',
    'public/assets/*.js',
    'public/assets/*.json'
  ], {
    dot: true
  }, cb);
});

gulp.task('build_application_css', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/stylesheets");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("application.css");

  return gulp.src(chain)
    .pipe(concat('application.less'))
    .pipe(gulpif(isLess, gulp_less()))
    .pipe(gulpif(!dev, minifyCSS({
      keepBreaks: false
    })))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('build_vendor_css', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/stylesheets");
  sc.appendPath("vendor/assets/stylesheets");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("vendor.css");

  return gulp.src(chain)
    .pipe(concat('vendor.css'))
    .pipe(minifyCSS({
      keepBreaks: false
    }))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('build_application_js', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/javascripts");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("application.js");

  return gulp.src(chain)
    .pipe(gulpif(isCoffee,
      coffee({
        bare: true
      }) // Compile coffeescript
      .on("error", gutil.log)
    ))
    .pipe(concat('application.js'))
    .pipe(ngAnnotate())
    .pipe(gulpif(!dev, uglify()))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('build_vendor_js', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/javascripts");
  sc.appendPath("vendor/assets/javascripts");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("vendor.js");

  return gulp.src(chain)
    .pipe(concat('vendor.js'))
    //.pipe(gulpif(!dev, uglify()))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('compile', ['clean', 'build_application_js', 'build_vendor_js', 'build_application_css', 'build_vendor_css'], function() {
  if (!dev) {
    return gulp.src(['public/assets/build/*.css', 'public/assets/build/*.js'])
      .pipe(rev())
      .pipe(gulp.dest('./public/assets'))
      .pipe(manifest())
      .pipe(gulp.dest('./public/assets'));
  }
});

gulp.task('default', ['compile'])
<commit_msg>remove env check from gulp<commit_after>var gulp = require('gulp');
var del = require('del');
var gulp_less = require('gulp-less');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var coffee = require("gulp-coffee");
var ngAnnotate = require('gulp-ng-annotate');
var gutil = require('gulp-util');
var rev = require('gulp-rev');
var manifest = require('gulp-rev-rails-manifest');
var gulpif = require('gulp-if');
var SprocketsChain = require("sprockets-chain");

var isCoffee = function(file) {
  return file.path.indexOf(".coffee") > -1
}

var isLess = function(file) {
  return file.path.indexOf(".less") > -1
}

var needsMinify = function(file) {
  return file.path.indexOf(".min") < 0
}

gulp.task('clean', function(cb) {
  del([
    'public/assets/build/*',
    'public/assets/*.css',
    'public/assets/*.js',
    'public/assets/*.json'
  ], {
    dot: true
  }, cb);
});

gulp.task('build_application_css', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/stylesheets");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("application.css");

  return gulp.src(chain)
    .pipe(concat('application.less'))
    .pipe(gulpif(isLess, gulp_less()))
    .pipe(minifyCSS({
      keepBreaks: false
    }))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('build_vendor_css', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/stylesheets");
  sc.appendPath("vendor/assets/stylesheets");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("vendor.css");

  return gulp.src(chain)
    .pipe(concat('vendor.css'))
    .pipe(minifyCSS({
      keepBreaks: false
    }))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('build_application_js', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/javascripts");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("application.js");

  return gulp.src(chain)
    .pipe(gulpif(isCoffee,
      coffee({
        bare: true
      }) // Compile coffeescript
      .on("error", gutil.log)
    ))
    .pipe(concat('application.js'))
    .pipe(ngAnnotate())
    .pipe(uglify())
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('build_vendor_js', function() {
  var sc = new SprocketsChain();
  sc.appendPath("app/assets/javascripts");
  sc.appendPath("vendor/assets/javascripts");
  sc.appendPath("vendor/assets/components");
  var chain = sc.depChain("vendor.js");

  return gulp.src(chain)
    .pipe(concat('vendor.js'))
    //.pipe(gulpif(!dev, uglify()))
    .pipe(gulp.dest('./public/assets/build'));
});

gulp.task('compile', ['clean', 'build_application_js', 'build_vendor_js', 'build_application_css', 'build_vendor_css'], function() {
  return gulp.src(['public/assets/build/*.css', 'public/assets/build/*.js'])
    .pipe(rev())
    .pipe(gulp.dest('./public/assets'))
    .pipe(manifest())
    .pipe(gulp.dest('./public/assets'));
});

gulp.task('default', ['compile'])
<|endoftext|>


<commit_before>/**
 * @package assets
 */

(function($, Symphony) {

	// always put try/catches into their
	// own function to prevent callers from
	// going into un-optimized hell
	var save = function (storage, value) {
		// Put in a try/catch in case something goes wrong (no space, privileges etc)
		try {
			window.localStorage[storage] = value;
		}
		catch(e) {
			window.onerror(e.message);
		}
	};

	/**
	 * Create collapsible elements.
	 *
	 * @name $.symphonyCollapsible
	 * @class
	 *
	 * @param {Object} options An object specifying containing the attributes specified below
	 * @param {String} [options.items='.instance'] Selector to find collapsible items within the container
	 * @param {String} [options.handles='.header:first'] Selector to find clickable handles to trigger interaction
	 * @param {String} [options.content='.content'] Selector to find hideable content area
	 * @param {Boolean} [options.save_state=true] Stores states of instances using local storage
	 * @param {String} [options.storage='symphony.collapsible.area.page.id'] Namespace used for local storage
	 * @param {Integer} [options.delay=250'] Time delay for animations
	 *
	 * @example

			var collapsible = $('#duplicator').symphonyCollapsible({
				items:		'.instance',
				handles:	'.header span'
			});
			collapsible.collapseAll();
	 */
	$.fn.symphonyCollapsible = function(options) {
		var objects = this,
			settings = {
				items: '.instance',
				handles: '.frame-header',
				content: '.content',
				ignore: '.ignore',
				save_state: true,
				storage: 'symphony.collapsible.' + Symphony.Context.get('context-id'),
				delay: 250
			};

		$.extend(settings, options);

	/*-----------------------------------------------------------------------*/

		objects.each(function collapsible(index) {
			var object = $(this),
				storage = settings.storage + '.' + index + '.collapsed';

			var getDuration = function (duration) {
				return $.isNumeric(duration) ? duration : settings.delay;
			};

		/*---------------------------------------------------------------------
			Events
		---------------------------------------------------------------------*/

			var collapseItem = function collapse(item, duration) {
				var heightMin = 0;

				// customization point
				item.trigger('collapsebefore.collapsible', settings);

				heightMin = item.data('heightMin');

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
					item.trigger('collapsestart.collapsible');
				}

				// Collapse item
				item.addClass('collapsed');
				item.css('max-height', heightMin);

				if(duration !== 0) {
					setTimeout(function() {
						item.trigger('animationend.collapsible');
						item.trigger('animationend.duplicator');
					}, duration);
				}
			};

			// Collapse item
			object.on('collapse.collapsible', settings.items, function collapse(event, duration) {
				var item = $(this);
				collapseItem(item, getDuration(duration));
			});

			// Collapse all items
			object.on('collapseall.collapsible', function collapseAll(event) {
				var items = object.find(settings.items + ':not(.collapsed)'),
					visibles = Symphony.Utilities.inSight(items),
					invisibles = visibles.eq(-1).nextAll().not('.collapsed');

				invisibles.each(function () { collapseItem($(this), 0); });
				visibles.each(function () { collapseItem($(this), settings.delay); });
				setTimeout(function collapseAllInvisible() {
					invisibles.trigger('animationend.collapsible');
				}, settings.delay + 100);
			});

			// Expand item
			var expandItem = function (item, duration) {
				var heightMax = 0;

				// customization point
				item.trigger('expandbefore.collapsible', settings);

				heightMax = item.data('heightMax');

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
					item.trigger('expandstart.collapsible');
				}

				// Collapse item
				item.removeClass('collapsed');
				item.css('max-height', heightMax);

				if(duration !== 0) {
					setTimeout(function() {
						item.trigger('animationend.collapsible');
					}, duration);
				}
			};

			object.on('expand.collapsible', settings.items, function expand(event, duration) {
				var item = $(this);
				expandItem(item, getDuration(duration));
			});

			// Expand all items
			object.on('expandall.collapsible', function expandAll(event) {
				var items = object.find(settings.items + '.collapsed'),
					visibles = Symphony.Utilities.inSight(items).filter('*:lt(4)'),
					invisibles = visibles.eq(-1).nextAll('.collapsed');

				visibles.addClass('js-animate-all'); // prevent focus
				visibles.each(function () { expandItem($(this), settings.delay); });
				setTimeout(function expandAllInvisible() {
					invisibles.addClass('js-animate-all'); // prevent focus
					invisibles.each(function () { expandItem($(this), 0); });
					invisibles.trigger('animationend.collapsible');
				}, settings.delay + 100);
			});

			// Finish animations
			object.on('animationend.collapsible', settings.items, function finish(event) {
				var item = $(this);

				// Trigger events
				if(item.is('.collapsed')) {
					item.trigger('collapsestop.collapsible');
				}
				else {
					item.trigger('expandstop.collapsible');
				}

				// clean up
				item.removeClass('js-animate js-animate-all');
			});

			// Toggle single item
			object.on('click.collapsible', settings.handles, function toggle(event) {
				var handle = $(this),
					item = handle.closest(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore) && !item.is('.locked')) {

					// Expand
					if(item.is('.collapsed')) {
						expandItem(item, settings.delay);
					}

					// Collapse
					else {
						collapseItem(item, settings.delay);
					}
				}
			});

			// Toggle all
			object.on('dblclick.collapsible', settings.handles, function toogleAll(event) {
				var handle = $(this),
					item = handle.closest(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore)) {

					// Expand all
					if(item.is('.collapsed')) {
						object.trigger('expandall.collapsible');
					}

					// Collapse all
					else {
						object.trigger('collapseall.collapsible');
					}
				}
			});

			// Save states
			var saveTimer = 0;
			object.on('collapsestop.collapsible expandstop.collapsible store.collapsible', settings.items, function saveState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true) {
					// save it to local storage, delayed, once
					clearTimeout(saveTimer);
					saveTimer = setTimeout(function () {
						var collapsed = object.find(settings.items).map(function(index) {
							if($(this).is('.collapsed')) {
								return index;
							};
						}).get().join(',');

						save(storage, collapsed);
					}, settings.delay);
				}
			});

			// Restore states
			object.on('restore.collapsible', function restoreState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true && window.localStorage[storage]) {
					$.each(window.localStorage[storage].split(','), function(index, value) {
						var collapsed = object.find(settings.items).eq(value);
						if(collapsed.has('.invalid').length == 0) {
							collapseItem(collapsed, 0);
						}
					});
				}
			});

			// Refresh state storage after ordering
			object.on('orderstop.orderable', function refreshOrderedState(event) {
				object.find(settings.items).trigger('store.collapsible');
			});

			// Refresh state storage after deleting and instance
			object.on('destructstop.duplicator', settings.items, function refreshState() {
				$(this).trigger('store.collapsible');
			});

			// Update sizes
			object.on('updatesize.collapsible', settings.items, function updateSizes() {
				var item = $(this),
					min = item.find(settings.handles).outerHeight(true),
					max = min + item.find(settings.content).outerHeight(true);

				item.data('heightMin', min);
				item.data('heightMax', max);
			});

			// Set sizes
			object.on('setsize.collapsible', settings.items, function setSizes() {
				var item = $(this);
				var heightMin = item.data('heightMin');
				var heightMax = item.data('heightMax');
				item.css({
					'min-height': heightMin,
					'max-height': heightMax
				});
			});

		/*---------------------------------------------------------------------
			Initialisation
		---------------------------------------------------------------------*/

			// Prepare interface
			object.addClass('collapsible').find(settings.items).each(function() {
				var item = $(this);
				item.addClass('instance');
				item.trigger('updatesize.collapsible');
				item.trigger('setsize.collapsible');
			});

			// Restore states
			object.trigger('restore.collapsible');
		});

	/*-----------------------------------------------------------------------*/

		return objects;
	};

})(window.jQuery, window.Symphony);
<commit_msg>Removed double click action<commit_after>/**
 * @package assets
 */

(function($, Symphony) {

	// always put try/catches into their
	// own function to prevent callers from
	// going into un-optimized hell
	var save = function (storage, value) {
		// Put in a try/catch in case something goes wrong (no space, privileges etc)
		try {
			window.localStorage[storage] = value;
		}
		catch(e) {
			window.onerror(e.message);
		}
	};

	/**
	 * Create collapsible elements.
	 *
	 * @name $.symphonyCollapsible
	 * @class
	 *
	 * @param {Object} options An object specifying containing the attributes specified below
	 * @param {String} [options.items='.instance'] Selector to find collapsible items within the container
	 * @param {String} [options.handles='.header:first'] Selector to find clickable handles to trigger interaction
	 * @param {String} [options.content='.content'] Selector to find hideable content area
	 * @param {Boolean} [options.save_state=true] Stores states of instances using local storage
	 * @param {String} [options.storage='symphony.collapsible.area.page.id'] Namespace used for local storage
	 * @param {Integer} [options.delay=250'] Time delay for animations
	 *
	 * @example

			var collapsible = $('#duplicator').symphonyCollapsible({
				items:		'.instance',
				handles:	'.header span'
			});
			collapsible.collapseAll();
	 */
	$.fn.symphonyCollapsible = function(options) {
		var objects = this,
			settings = {
				items: '.instance',
				handles: '.frame-header',
				content: '.content',
				ignore: '.ignore',
				save_state: true,
				storage: 'symphony.collapsible.' + Symphony.Context.get('context-id'),
				delay: 250
			};

		$.extend(settings, options);

	/*-----------------------------------------------------------------------*/

		objects.each(function collapsible(index) {
			var object = $(this),
				storage = settings.storage + '.' + index + '.collapsed';

			var getDuration = function (duration) {
				return $.isNumeric(duration) ? duration : settings.delay;
			};

		/*---------------------------------------------------------------------
			Events
		---------------------------------------------------------------------*/

			var collapseItem = function collapse(item, duration) {
				var heightMin = 0;

				// customization point
				item.trigger('collapsebefore.collapsible', settings);

				heightMin = item.data('heightMin');

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
					item.trigger('collapsestart.collapsible');
				}

				// Collapse item
				item.addClass('collapsed');
				item.css('max-height', heightMin);

				if(duration !== 0) {
					setTimeout(function() {
						item.trigger('animationend.collapsible');
						item.trigger('animationend.duplicator');
					}, duration);
				}
			};

			// Collapse item
			object.on('collapse.collapsible', settings.items, function collapse(event, duration) {
				var item = $(this);
				collapseItem(item, getDuration(duration));
			});

			// Collapse all items
			object.on('collapseall.collapsible', function collapseAll(event) {
				var items = object.find(settings.items + ':not(.collapsed)'),
					visibles = Symphony.Utilities.inSight(items),
					invisibles = visibles.eq(-1).nextAll().not('.collapsed');

				invisibles.each(function () { collapseItem($(this), 0); });
				visibles.each(function () { collapseItem($(this), settings.delay); });
				setTimeout(function collapseAllInvisible() {
					invisibles.trigger('animationend.collapsible');
				}, settings.delay + 100);
			});

			// Expand item
			var expandItem = function (item, duration) {
				var heightMax = 0;

				// customization point
				item.trigger('expandbefore.collapsible', settings);

				heightMax = item.data('heightMax');

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
					item.trigger('expandstart.collapsible');
				}

				// Collapse item
				item.removeClass('collapsed');
				item.css('max-height', heightMax);

				if(duration !== 0) {
					setTimeout(function() {
						item.trigger('animationend.collapsible');
					}, duration);
				}
			};

			object.on('expand.collapsible', settings.items, function expand(event, duration) {
				var item = $(this);
				expandItem(item, getDuration(duration));
			});

			// Expand all items
			object.on('expandall.collapsible', function expandAll(event) {
				var items = object.find(settings.items + '.collapsed'),
					visibles = Symphony.Utilities.inSight(items).filter('*:lt(4)'),
					invisibles = visibles.eq(-1).nextAll('.collapsed');

				visibles.addClass('js-animate-all'); // prevent focus
				visibles.each(function () { expandItem($(this), settings.delay); });
				setTimeout(function expandAllInvisible() {
					invisibles.addClass('js-animate-all'); // prevent focus
					invisibles.each(function () { expandItem($(this), 0); });
					invisibles.trigger('animationend.collapsible');
				}, settings.delay + 100);
			});

			// Finish animations
			object.on('animationend.collapsible', settings.items, function finish(event) {
				var item = $(this);

				// Trigger events
				if(item.is('.collapsed')) {
					item.trigger('collapsestop.collapsible');
				}
				else {
					item.trigger('expandstop.collapsible');
				}

				// clean up
				item.removeClass('js-animate js-animate-all');
			});

			// Toggle single item
			object.on('click.collapsible', settings.handles, function toggle(event) {
				var handle = $(this),
					item = handle.closest(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore) && !item.is('.locked')) {

					// Expand
					if(item.is('.collapsed')) {
						expandItem(item, settings.delay);
					}

					// Collapse
					else {
						collapseItem(item, settings.delay);
					}
				}
			});

			// Save states
			var saveTimer = 0;
			object.on('collapsestop.collapsible expandstop.collapsible store.collapsible', settings.items, function saveState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true) {
					// save it to local storage, delayed, once
					clearTimeout(saveTimer);
					saveTimer = setTimeout(function () {
						var collapsed = object.find(settings.items).map(function(index) {
							if($(this).is('.collapsed')) {
								return index;
							};
						}).get().join(',');

						save(storage, collapsed);
					}, settings.delay);
				}
			});

			// Restore states
			object.on('restore.collapsible', function restoreState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true && window.localStorage[storage]) {
					$.each(window.localStorage[storage].split(','), function(index, value) {
						var collapsed = object.find(settings.items).eq(value);
						if(collapsed.has('.invalid').length == 0) {
							collapseItem(collapsed, 0);
						}
					});
				}
			});

			// Refresh state storage after ordering
			object.on('orderstop.orderable', function refreshOrderedState(event) {
				object.find(settings.items).trigger('store.collapsible');
			});

			// Refresh state storage after deleting and instance
			object.on('destructstop.duplicator', settings.items, function refreshState() {
				$(this).trigger('store.collapsible');
			});

			// Update sizes
			object.on('updatesize.collapsible', settings.items, function updateSizes() {
				var item = $(this),
					min = item.find(settings.handles).outerHeight(true),
					max = min + item.find(settings.content).outerHeight(true);

				item.data('heightMin', min);
				item.data('heightMax', max);
			});

			// Set sizes
			object.on('setsize.collapsible', settings.items, function setSizes() {
				var item = $(this);
				var heightMin = item.data('heightMin');
				var heightMax = item.data('heightMax');
				item.css({
					'min-height': heightMin,
					'max-height': heightMax
				});
			});

		/*---------------------------------------------------------------------
			Initialisation
		---------------------------------------------------------------------*/

			// Prepare interface
			object.addClass('collapsible').find(settings.items).each(function() {
				var item = $(this);
				item.addClass('instance');
				item.trigger('updatesize.collapsible');
				item.trigger('setsize.collapsible');
			});

			// Restore states
			object.trigger('restore.collapsible');
		});

	/*-----------------------------------------------------------------------*/

		return objects;
	};

})(window.jQuery, window.Symphony);
<|endoftext|>


<commit_before>/* eslint-disable no-param-reassign */
const core = require('@actions/core');
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const { integrationFolder, testFiles } = require('../../config/cypress.json');
const findImports = require('find-imports');

const IS_MASTER_BUILD = process.env.IS_MASTER_BUILD === 'true';
const IS_CHANGED_APPS_BUILD = Boolean(process.env.APP_ENTRIES);
const APPS_HAVE_URLS = Boolean(process.env.APP_URLS);

function getImports(filePath) {
  return findImports(filePath, {
    absoluteImports: true,
    relativeImports: true,
    packageImports: false,
  });
}

function getAppNameFromFilePath(filePath) {
  return filePath.split('/')[2];
}

/* Function takes an import reference and returns the path
 * to the referenced file from 'src/' if the reference begins
 * with 'applications/' or starts with '../'. Otherwise
 * it returns the given reference.
 */
function getImportPath(filePathAsArray, importRef) {
  if (importRef.startsWith('applications/')) {
    return `src/${importRef}`;
  } else if (importRef.startsWith('../')) {
    const numDirsUp = importRef.split('/').filter(str => str === '..').length;

    return importRef.replace(
      '../'.repeat(numDirsUp),
      `${filePathAsArray
        .slice(0, filePathAsArray.length - 1 - numDirsUp)
        .join('/')}/`,
    );
  }

  return importRef;
}

function importIsFromOtherApplication(appName, importPath) {
  return (
    importPath.startsWith('src/applications') &&
    !importPath.startsWith(`src/applications/${appName}`)
  );
}

function updateGraph(graph, appName, importerFilePath, importeeFilePath) {
  const importAppName = getAppNameFromFilePath(importeeFilePath);

  if (!graph[importAppName]) {
    graph[importAppName] = {
      appsToTest: [importAppName],
      appsThatThisAppImportsFrom: {},
      appsThatImportFromThisApp: {},
    };
  }

  graph[importAppName].appsToTest.push(appName);

  if (!graph[appName].appsThatThisAppImportsFrom[importAppName]) {
    graph[appName].appsThatThisAppImportsFrom[importAppName] = {
      filesImported: [],
    };
  }

  graph[appName].appsThatThisAppImportsFrom[importAppName].filesImported.push({
    importer: importerFilePath,
    importee: importeeFilePath,
  });

  if (!graph[importAppName].appsThatImportFromThisApp[appName]) {
    graph[importAppName].appsThatImportFromThisApp[appName] = {
      filesImported: [],
    };
  }

  graph[importAppName].appsThatImportFromThisApp[appName].filesImported.push({
    importer: importerFilePath,
    importee: importeeFilePath,
  });
}

function buildGraph() {
  const graph = {};
  const files = ['src/applications/**/*.*', '!src/applications/*.*'];
  const imports = getImports(files);

  Object.keys(imports).forEach(importerFilePath => {
    const appName = getAppNameFromFilePath(importerFilePath);
    const filePathAsArray = importerFilePath.split('/');

    if (!graph[appName]) {
      graph[appName] = {
        appsToTest: [appName],
        appsThatThisAppImportsFrom: {},
        appsThatImportFromThisApp: {},
      };
    }

    imports[importerFilePath].forEach(importRef => {
      const importeeFilePath = getImportPath(filePathAsArray, importRef);

      if (importIsFromOtherApplication(appName, importeeFilePath)) {
        updateGraph(graph, appName, importerFilePath, importeeFilePath);
      }
    });
  });

  return graph;
}

function dedupeGraph(graph) {
  Object.keys(graph).forEach(app => {
    graph[app].appsToTest = [...new Set(graph[app].appsToTest)];
  });

  return graph;
}

function selectedTests(graph, pathsOfChangedFiles) {
  const tests = [];
  const applications = [];
  const applicationNames = pathsOfChangedFiles
    .filter(filePath => !filePath.endsWith('.md'))
    .map(filePath => filePath.split('/')[2]);

  [...new Set(applicationNames)].forEach(app => {
    if (graph[app]) {
      // Lookup app in cross-app imports graph to reference which app's tests
      // should run
      applications.push(...graph[app].appsToTest);
    }
  });

  [...new Set(applications)].forEach(app => {
    const selectedTestsPattern = path.join(
      __dirname,
      '../..',
      'src/applications',
      `${app}/**/tests/**/*.cypress.spec.js?(x)`,
    );

    tests.push(...glob.sync(selectedTestsPattern));
  });

  // Only run the mega menu test for changed apps builds,
  // otherwise run all tests in src/platform for full builds
  if (IS_CHANGED_APPS_BUILD) {
    const megaMenuTestPath = path.join(
      __dirname,
      '../..',
      'src/platform/site-wide/mega-menu/tests/megaMenu.cypress.spec.js',
    );

    // Ensure changed apps have URLs to run header test on
    if (APPS_HAVE_URLS && fs.existsSync(megaMenuTestPath))
      tests.push(megaMenuTestPath);
  } else {
    const defaultTestsPattern = path.join(
      __dirname,
      '../..',
      'src/platform',
      '**/tests/**/*.cypress.spec.js?(x)',
    );

    tests.push(...glob.sync(defaultTestsPattern));
  }

  return tests;
}

function allTests() {
  const pattern = path.join(__dirname, '../..', integrationFolder, testFiles);
  return glob.sync(pattern);
}

function selectTests(graph, pathsOfChangedFiles) {
  if (IS_MASTER_BUILD) {
    return allTests();
  } else {
    let allMdFiles = true;
    let allMdAndOrSrcApplicationsFiles = true;

    for (let i = 0; i < pathsOfChangedFiles.length; i += 1) {
      if (!pathsOfChangedFiles[i].endsWith('.md')) {
        allMdFiles = false;
      }

      if (
        !pathsOfChangedFiles[i].endsWith('.md') &&
        !pathsOfChangedFiles[i].startsWith('src/applications')
      ) {
        allMdAndOrSrcApplicationsFiles = false;
      }

      if (allMdFiles === false && allMdAndOrSrcApplicationsFiles === false) {
        break;
      }
    }

    if (allMdFiles) {
      return [];
    } else if (allMdAndOrSrcApplicationsFiles) {
      return selectedTests(graph, pathsOfChangedFiles);
    } else {
      return allTests();
    }
  }
}

function exportVariables(tests) {
  core.exportVariable('TESTS', tests);
}

function run() {
  const pathsOfChangedFiles = process.env.CHANGED_FILE_PATHS.split(' ');
  const graph = dedupeGraph(buildGraph());
  const tests = selectTests(graph, pathsOfChangedFiles);
  exportVariables(tests);
}

if (process.env.CHANGED_FILE_PATHS) {
  run();
}

module.exports = {
  buildGraph,
  dedupeGraph,
};
<commit_msg>Update Cypress test selection to run on master (#19925)<commit_after>/* eslint-disable no-param-reassign */
const core = require('@actions/core');
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const { integrationFolder, testFiles } = require('../../config/cypress.json');
const findImports = require('find-imports');

const IS_MASTER_BUILD = process.env.IS_MASTER_BUILD === 'true';
const IS_CHANGED_APPS_BUILD = Boolean(process.env.APP_ENTRIES);
const APPS_HAVE_URLS = Boolean(process.env.APP_URLS);

function getImports(filePath) {
  return findImports(filePath, {
    absoluteImports: true,
    relativeImports: true,
    packageImports: false,
  });
}

function getAppNameFromFilePath(filePath) {
  return filePath.split('/')[2];
}

/* Function takes an import reference and returns the path
 * to the referenced file from 'src/' if the reference begins
 * with 'applications/' or starts with '../'. Otherwise
 * it returns the given reference.
 */
function getImportPath(filePathAsArray, importRef) {
  if (importRef.startsWith('applications/')) {
    return `src/${importRef}`;
  } else if (importRef.startsWith('../')) {
    const numDirsUp = importRef.split('/').filter(str => str === '..').length;

    return importRef.replace(
      '../'.repeat(numDirsUp),
      `${filePathAsArray
        .slice(0, filePathAsArray.length - 1 - numDirsUp)
        .join('/')}/`,
    );
  }

  return importRef;
}

function importIsFromOtherApplication(appName, importPath) {
  return (
    importPath.startsWith('src/applications') &&
    !importPath.startsWith(`src/applications/${appName}`)
  );
}

function updateGraph(graph, appName, importerFilePath, importeeFilePath) {
  const importAppName = getAppNameFromFilePath(importeeFilePath);

  if (!graph[importAppName]) {
    graph[importAppName] = {
      appsToTest: [importAppName],
      appsThatThisAppImportsFrom: {},
      appsThatImportFromThisApp: {},
    };
  }

  graph[importAppName].appsToTest.push(appName);

  if (!graph[appName].appsThatThisAppImportsFrom[importAppName]) {
    graph[appName].appsThatThisAppImportsFrom[importAppName] = {
      filesImported: [],
    };
  }

  graph[appName].appsThatThisAppImportsFrom[importAppName].filesImported.push({
    importer: importerFilePath,
    importee: importeeFilePath,
  });

  if (!graph[importAppName].appsThatImportFromThisApp[appName]) {
    graph[importAppName].appsThatImportFromThisApp[appName] = {
      filesImported: [],
    };
  }

  graph[importAppName].appsThatImportFromThisApp[appName].filesImported.push({
    importer: importerFilePath,
    importee: importeeFilePath,
  });
}

function buildGraph() {
  const graph = {};
  const files = ['src/applications/**/*.*', '!src/applications/*.*'];
  const imports = getImports(files);

  Object.keys(imports).forEach(importerFilePath => {
    const appName = getAppNameFromFilePath(importerFilePath);
    const filePathAsArray = importerFilePath.split('/');

    if (!graph[appName]) {
      graph[appName] = {
        appsToTest: [appName],
        appsThatThisAppImportsFrom: {},
        appsThatImportFromThisApp: {},
      };
    }

    imports[importerFilePath].forEach(importRef => {
      const importeeFilePath = getImportPath(filePathAsArray, importRef);

      if (importIsFromOtherApplication(appName, importeeFilePath)) {
        updateGraph(graph, appName, importerFilePath, importeeFilePath);
      }
    });
  });

  return graph;
}

function dedupeGraph(graph) {
  Object.keys(graph).forEach(app => {
    graph[app].appsToTest = [...new Set(graph[app].appsToTest)];
  });

  return graph;
}

function selectedTests(graph, pathsOfChangedFiles) {
  const tests = [];
  const applications = [];
  const applicationNames = pathsOfChangedFiles
    .filter(filePath => !filePath.endsWith('.md'))
    .map(filePath => filePath.split('/')[2]);

  [...new Set(applicationNames)].forEach(app => {
    if (graph[app]) {
      // Lookup app in cross-app imports graph to reference which app's tests
      // should run
      applications.push(...graph[app].appsToTest);
    }
  });

  [...new Set(applications)].forEach(app => {
    const selectedTestsPattern = path.join(
      __dirname,
      '../..',
      'src/applications',
      `${app}/**/tests/**/*.cypress.spec.js?(x)`,
    );

    tests.push(...glob.sync(selectedTestsPattern));
  });

  // Only run the mega menu test for changed apps builds,
  // otherwise run all tests in src/platform for full builds
  if (IS_CHANGED_APPS_BUILD) {
    const megaMenuTestPath = path.join(
      __dirname,
      '../..',
      'src/platform/site-wide/mega-menu/tests/megaMenu.cypress.spec.js',
    );

    // Ensure changed apps have URLs to run header test on
    if (APPS_HAVE_URLS && fs.existsSync(megaMenuTestPath))
      tests.push(megaMenuTestPath);
  } else {
    const defaultTestsPattern = path.join(
      __dirname,
      '../..',
      'src/platform',
      '**/tests/**/*.cypress.spec.js?(x)',
    );

    tests.push(...glob.sync(defaultTestsPattern));
  }

  return tests;
}

function allTests() {
  const pattern = path.join(__dirname, '../..', integrationFolder, testFiles);
  return glob.sync(pattern);
}

function selectTests(graph, pathsOfChangedFiles) {
  if (IS_MASTER_BUILD) {
    return allTests();
  } else {
    let allMdFiles = true;
    let allMdAndOrSrcApplicationsFiles = true;

    for (let i = 0; i < pathsOfChangedFiles.length; i += 1) {
      if (!pathsOfChangedFiles[i].endsWith('.md')) {
        allMdFiles = false;
      }

      if (
        !pathsOfChangedFiles[i].endsWith('.md') &&
        !pathsOfChangedFiles[i].startsWith('src/applications')
      ) {
        allMdAndOrSrcApplicationsFiles = false;
      }

      if (allMdFiles === false && allMdAndOrSrcApplicationsFiles === false) {
        break;
      }
    }

    if (allMdFiles) {
      return [];
    } else if (allMdAndOrSrcApplicationsFiles) {
      return selectedTests(graph, pathsOfChangedFiles);
    } else {
      return allTests();
    }
  }
}

function exportVariables(tests) {
  core.exportVariable('TESTS', tests);
}

function run() {
  const pathsOfChangedFiles = process.env.CHANGED_FILE_PATHS.split(' ');
  const graph = dedupeGraph(buildGraph());
  const tests = selectTests(graph, pathsOfChangedFiles);
  exportVariables(tests);
}

if (process.env.CHANGED_FILE_PATHS || IS_MASTER_BUILD) {
  run();
}

module.exports = {
  buildGraph,
  dedupeGraph,
};
<|endoftext|>