<commit_before>exports.run = (bot, message, params, config) => {
    if (!params[0]) {
      message.channel.sendMessage("check your dms :rocket:").catch(console.error);
      let modRole = message.guild.roles.find("name", "Staff");
      let adminRole = message.guild.roles.find("name", "Owner");
      var cmds = ``;
      cmds += `**Warning this is the dev rep so not all commands are here** \n\n **My Normal Commands are:** \n ${config.client.prefix}membercount \n ${config.client.prefix}serverinfo \n ${config.client.prefix}botservers \n ${config.client.prefix}date \n ${config.client.prefix}sourcecode \n ${config.client.prefix}avatar \n ${config.client.prefix}ping \n ${config.client.prefix}creator \n ${config.client.prefix}help \n ${config.client.prefix}stats \n ${config.client.prefix}myuserinfo`;
      if (message.member.roles.has(modRole.id) || config.creator.Jimmy.includes(message.author.id)) {
          cmds += `\n\n **My Staff commands are** \n ${config.client.prefix}embed [what you want to embed] \n ${config.client.prefix}addrole {user} [role] \n ${config.client.prefix}delrole {user} [role] \n ${config.client.prefix}announce [what you want to announce in #announcements] \n ${config.client.prefix}say [what you want to say] \n ${config.client.prefix}kick {user} \n \n more details on how to use these commands coming soon`;
      }
      if (message.member.roles.has(adminRole.id) || config.creator.Jimmy.includes(message.author.id)) {
          cmds += `\n\n **My Owner/Creator Commands are:** \n ${config.client.prefix}setbotavatarurl (only Jimmy) \n ${config.client.prefix}setstatus (only Jimmy) \n ${config.client.prefix}shutdown \n ${config.client.prefix}restart`;
      }
      message.author.sendMessage(" ", {
          embed: {
              color: 0x00b7c6,
          title: "Command List",
          description: cmds,
    }}).catch(console.error);
  } else {
    let command = params[0];
    if(bot.commands.has(command)) {
      command = bot.commands.get(command);
      message.channel.sendCode("asciidoc", `= ${command.help.name} = \n${command.help.description}\nusage::${command.help.usage}`);
    }
  }
};

exports.conf = {
  enabled: true,
  guildOnly: false,
  aliases: [],
  permLevel: 0
};

exports.help = {
  name : "help",
  description: "Returns page details from root's awesome bot guide.",
  usage: "help [command]"
};
<commit_msg>Update help.js<commit_after>exports.run = (bot, message, params, perms, config) => {
    if (!params[0]) {
      message.channel.sendMessage("check your dms :rocket:").catch(console.error);
      let modRole = message.guild.roles.find("name", "Staff");
      let adminRole = message.guild.roles.find("name", "Owner");
      var cmds = ``;
      cmds += `**Warning this is the dev rep so not all commands are here** \n\n **My Normal Commands are:** \n ${config.client.prefix}membercount \n ${config.client.prefix}serverinfo \n ${config.client.prefix}botservers \n ${config.client.prefix}date \n ${config.client.prefix}sourcecode \n ${config.client.prefix}avatar \n ${config.client.prefix}ping \n ${config.client.prefix}creator \n ${config.client.prefix}help \n ${config.client.prefix}stats \n ${config.client.prefix}myuserinfo`;
      if (message.member.roles.has(modRole.id) || config.creator.Jimmy.includes(message.author.id)) {
          cmds += `\n\n **My Staff commands are** \n ${config.client.prefix}embed [what you want to embed] \n ${config.client.prefix}addrole {user} [role] \n ${config.client.prefix}delrole {user} [role] \n ${config.client.prefix}announce [what you want to announce in #announcements] \n ${config.client.prefix}say [what you want to say] \n ${config.client.prefix}kick {user} \n \n more details on how to use these commands coming soon`;
      }
      if (message.member.roles.has(adminRole.id) || config.creator.Jimmy.includes(message.author.id)) {
          cmds += `\n\n **My Owner/Creator Commands are:** \n ${config.client.prefix}setbotavatarurl (only Jimmy) \n ${config.client.prefix}setstatus (only Jimmy) \n ${config.client.prefix}shutdown \n ${config.client.prefix}restart`;
      }
      message.author.sendMessage(" ", {
          embed: {
              color: 0x00b7c6,
          title: "Command List",
          description: cmds,
    }}).catch(console.error);
  } else {
    let command = params[0];
    if(bot.commands.has(command)) {
      command = bot.commands.get(command);
      message.channel.sendCode("asciidoc", `= ${command.help.name} = \n${command.help.description}\nusage::${command.help.usage}`);
    }
  }
};

exports.conf = {
  enabled: true,
  guildOnly: false,
  aliases: [],
  permLevel: 0
};

exports.help = {
  name : "help",
  description: "Returns page details from root's awesome bot guide.",
  usage: "help [command]"
};
<|endoftext|>


<commit_before>angular.module('pteraformer').directive('placeReference', function() {
  return {
    restrict: 'E',
    transclude: 'true',
    scope: {
      id: '@',
      geo: '@'
    },
    template: ' {{geo}} <ng-transclude></ng-transclude>',
    link: function ($scope, element, attrs) {
      element.bind('click', function () {
        element.html('You clicked me!');
      });
    }
  };
});
<commit_msg>convert geojson string to obj<commit_after>angular.module('pteraformer').directive('placeReference', function() {
  return {
    restrict: 'E',
    transclude: 'true',
    scope: {
      id: '@',
      geo: '@'
    },
    template: '<ng-transclude></ng-transclude>',
    link: function ($scope, element, attrs) {
      element.bind('click', function () {
        //element.html('You clicked me!');
        var geoObj = JSON.parse($scope.geo);
        console.log(geoObj);
      });
    }
  };
});
<|endoftext|>


<commit_before>/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');
var Lib = require('../../lib');
var Plots = require('../plots');
var Axes = require('./axes');
var constants = require('./constants');

exports.name = 'cartesian';

exports.attr = ['xaxis', 'yaxis'];

exports.idRoot = ['x', 'y'];

exports.idRegex = constants.idRegex;

exports.attrRegex = constants.attrRegex;

exports.attributes = require('./attributes');

exports.transitionAxes = require('./transition_axes');

exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
    var cdSubplot, cd, trace, i, j, k;

    var fullLayout = gd._fullLayout,
        subplots = Plots.getSubplotIds(fullLayout, 'cartesian'),
        calcdata = gd.calcdata,
        modules = fullLayout._modules;

    if(!Array.isArray(traces)) {
      // If traces is not provided, then it's a complete replot and missing
      // traces are removed
        traces = [];
        for(i = 0; i < calcdata.length; i++) {
            traces.push(i);
        }
    }

    for(i = 0; i < subplots.length; i++) {
        var subplot = subplots[i],
            subplotInfo = fullLayout._plots[subplot];

        // Get all calcdata for this subplot:
        cdSubplot = [];
        var pcd;
        for(j = 0; j < calcdata.length; j++) {
            cd = calcdata[j];
            trace = cd[0].trace;

            // Skip trace if whitelist provided and it's not whitelisted:
            // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
            if(trace.xaxis + trace.yaxis === subplot) {
                // If this trace is specifically requested, add it to the list:
                if(traces.indexOf(trace.index) !== -1) {
                    // Okay, so example: traces 0, 1, and 2 have fill = tonext. You animate
                    // traces 0 and 2. Trace 1 also needs to be updated, otherwise its fill
                    // is outdated. So this retroactively adds the previous trace if the
                    // traces are interdependent.
                    if(pcd &&
                            ['tonextx', 'tonexty', 'tonext'].indexOf(trace.fill) !== -1 &&
                            cdSubplot.indexOf(pcd) === -1) {
                        cdSubplot.push(pcd);
                    }

                    cdSubplot.push(cd);
                }

                // Track the previous trace on this subplot for the retroactive-add step
                // above:
                pcd = cd;
            }
        }

        // remove old traces, then redraw everything
        // TODO: scatterlayer is manually excluded from this since it knows how
        // to update instead of fully removing and redrawing every time. The
        // remaining plot traces should also be able to do this. Once implemented,
        // we won't need this - which should sometimes be a big speedup.
        if(subplotInfo.plot) {
            subplotInfo.plot.selectAll('g:not(.scatterlayer)').selectAll('g.trace').remove();
        }

        // Plot all traces for each module at once:
        for(j = 0; j < modules.length; j++) {
            var _module = modules[j];

            // skip over non-cartesian trace modules
            if(_module.basePlotModule.name !== 'cartesian') continue;

            // plot all traces of this type on this subplot at once
            var cdModule = [];
            for(k = 0; k < cdSubplot.length; k++) {
                cd = cdSubplot[k];
                trace = cd[0].trace;

                if((trace._module === _module) && (trace.visible === true)) {
                    cdModule.push(cd);
                }
            }

            _module.plot(gd, subplotInfo, cdModule, transitionOpts, makeOnCompleteCallback);
        }
    }
};

exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
    var oldModules = oldFullLayout._modules || [],
        newModules = newFullLayout._modules || [];

    var hadScatter, hasScatter, i;

    for(i = 0; i < oldModules.length; i++) {
        if(oldModules[i].name === 'scatter') {
            hadScatter = true;
            break;
        }
    }

    for(i = 0; i < newModules.length; i++) {
        if(newModules[i].name === 'scatter') {
            hasScatter = true;
            break;
        }
    }

    if(hadScatter && !hasScatter) {
        var oldPlots = oldFullLayout._plots,
            ids = Object.keys(oldPlots || {});

        for(i = 0; i < ids.length; i++) {
            var subplotInfo = oldPlots[ids[i]];

            if(subplotInfo.plot) {
                subplotInfo.plot.select('g.scatterlayer')
                    .selectAll('g.trace')
                    .remove();
            }
        }
    }

    var hadCartesian = (oldFullLayout._has && oldFullLayout._has('cartesian'));
    var hasCartesian = (newFullLayout._has && newFullLayout._has('cartesian'));

    if(hadCartesian && !hasCartesian) {
        var subplotLayers = oldFullLayout._cartesianlayer.selectAll('.subplot');

        subplotLayers.call(purgeSubplotLayers, oldFullLayout);
        oldFullLayout._defs.selectAll('.axesclip').remove();
    }
};

exports.drawFramework = function(gd) {
    var fullLayout = gd._fullLayout,
        subplotData = makeSubplotData(gd);

    var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot')
        .data(subplotData, Lib.identity);

    subplotLayers.enter().append('g')
        .classed('subplot', true);

    subplotLayers.order();

    subplotLayers.exit()
        .call(purgeSubplotLayers, fullLayout);

    subplotLayers.each(function(subplot) {
        var plotgroup = d3.select(this),
            plotinfo = fullLayout._plots[subplot];

        // references to any subplots overlaid on this one,
        // filled in makeSubplotLayer
        plotinfo.overlays = [];

        plotgroup.call(makeSubplotLayer, gd, subplot);

        // make separate drag layers for each subplot,
        // but append them to paper rather than the plot groups,
        // so they end up on top of the rest
        plotinfo.draglayer = joinLayer(fullLayout._draggers, 'g', subplot);
    });
};

function makeSubplotData(gd) {
    var fullLayout = gd._fullLayout,
        subplots = Axes.getSubplots(gd);

    var subplotData = [],
        overlays = [];

    for(var i = 0; i < subplots.length; i++) {
        var subplot = subplots[i],
            plotinfo = fullLayout._plots[subplot];

        var xa = plotinfo.xaxis,
            ya = plotinfo.yaxis;

        // is this subplot overlaid on another?
        // ax.overlaying is the id of another axis of the same
        // dimension that this one overlays to be an overlaid subplot,
        // the main plot must exist make sure we're not trying to
        // overlay on an axis that's already overlaying another
        var xa2 = Axes.getFromId(gd, xa.overlaying) || xa;
        if(xa2 !== xa && xa2.overlaying) {
            xa2 = xa;
            xa.overlaying = false;
        }

        var ya2 = Axes.getFromId(gd, ya.overlaying) || ya;
        if(ya2 !== ya && ya2.overlaying) {
            ya2 = ya;
            ya.overlaying = false;
        }

        var mainplot = xa2._id + ya2._id;
        if(mainplot !== subplot && subplots.indexOf(mainplot) !== -1) {
            plotinfo.mainplot = mainplot;
            overlays.push(subplot);

            // for now force overlays to overlay completely... so they
            // can drag together correctly and share backgrounds.
            // Later perhaps we make separate axis domain and
            // tick/line domain or something, so they can still share
            // the (possibly larger) dragger and background but don't
            // have to both be drawn over that whole domain
            xa.domain = xa2.domain.slice();
            ya.domain = ya2.domain.slice();
        }
        else {
            subplotData.push(subplot);
        }
    }

    // main subplots before overlays
    subplotData = subplotData.concat(overlays);

    return subplotData;
}

function makeSubplotLayer(plotgroup, gd, subplot) {
    var fullLayout = gd._fullLayout,
        plotinfo = fullLayout._plots[subplot];

    // keep reference to plotgroup in _plots object
    plotinfo.plotgroup = plotgroup;

    // add class corresponding to the subplot id
    plotgroup.classed(subplot, true);

    // Layers to keep plot types in the right order.
    // from back to front:
    // 1. heatmaps, 2D histos and contour maps
    // 2. bars / 1D histos
    // 3. errorbars for bars and scatter
    // 4. scatter
    // 5. box plots
    function plotLayers(parent) {
        joinLayer(parent, 'g', 'imagelayer');
        joinLayer(parent, 'g', 'maplayer');
        joinLayer(parent, 'g', 'barlayer');
        joinLayer(parent, 'g', 'boxlayer');
        joinLayer(parent, 'g', 'scatterlayer');
    }

    if(!plotinfo.mainplot) {
        plotinfo.bg = joinLayer(plotgroup, 'rect', 'bg');
        plotinfo.bg.style('stroke-width', 0);

        var backLayer = joinLayer(plotgroup, 'g', 'layer-subplot');
        plotinfo.shapelayer = joinLayer(backLayer, 'g', 'shapelayer');
        plotinfo.imagelayer = joinLayer(backLayer, 'g', 'imagelayer');

        plotinfo.gridlayer = joinLayer(plotgroup, 'g', 'gridlayer');
        plotinfo.overgrid = joinLayer(plotgroup, 'g', 'overgrid');

        plotinfo.zerolinelayer = joinLayer(plotgroup, 'g', 'zerolinelayer');
        plotinfo.overzero = joinLayer(plotgroup, 'g', 'overzero');

        plotinfo.plot = joinLayer(plotgroup, 'g', 'plot');
        plotinfo.overplot = joinLayer(plotgroup, 'g', 'overplot');

        plotinfo.xlines = joinLayer(plotgroup, 'path', 'xlines');
        plotinfo.ylines = joinLayer(plotgroup, 'path', 'ylines');
        plotinfo.overlines = joinLayer(plotgroup, 'g', 'overlines');

        plotinfo.xaxislayer = joinLayer(plotgroup, 'g', 'xaxislayer');
        plotinfo.yaxislayer = joinLayer(plotgroup, 'g', 'yaxislayer');
        plotinfo.overaxes = joinLayer(plotgroup, 'g', 'overaxes');
    }
    else {

        // now make the components of overlaid subplots
        // overlays don't have backgrounds, and append all
        // their other components to the corresponding
        // extra groups of their main plots.

        var mainplot = fullLayout._plots[plotinfo.mainplot];
        mainplot.overlays.push(plotinfo);

        plotinfo.gridlayer = joinLayer(mainplot.overgrid, 'g', subplot);
        plotinfo.zerolinelayer = joinLayer(mainplot.overzero, 'g', subplot);

        plotinfo.plot = joinLayer(mainplot.overplot, 'g', subplot);
        plotinfo.xlines = joinLayer(mainplot.overlines, 'path', subplot);
        plotinfo.ylines = joinLayer(mainplot.overlines, 'path', subplot);
        plotinfo.xaxislayer = joinLayer(mainplot.overaxes, 'g', subplot);
        plotinfo.yaxislayer = joinLayer(mainplot.overaxes, 'g', subplot);
    }

    // common attributes for all subplots, overlays or not
    plotinfo.plot.call(plotLayers);

    plotinfo.xlines
        .style('fill', 'none')
        .classed('crisp', true);

    plotinfo.ylines
        .style('fill', 'none')
        .classed('crisp', true);
}

function purgeSubplotLayers(layers, fullLayout) {
    if(!layers) return;

    layers.each(function(subplot) {
        var plotgroup = d3.select(this),
            clipId = 'clip' + fullLayout._uid + subplot + 'plot';

        plotgroup.remove();
        fullLayout._draggers.selectAll('g.' + subplot).remove();
        fullLayout._defs.select('#' + clipId).remove();

        // do not remove individual axis <clipPath>s here
        // as other subplots may need them
    });
}

function joinLayer(parent, nodeType, className) {
    var layer = parent.selectAll('.' + className)
        .data([0]);

    layer.enter().append(nodeType)
        .classed(className, true);

    return layer;
}
<commit_msg>make makeSubplotLayer agnostic to fullLayout<commit_after>/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');
var Lib = require('../../lib');
var Plots = require('../plots');
var Axes = require('./axes');
var constants = require('./constants');

exports.name = 'cartesian';

exports.attr = ['xaxis', 'yaxis'];

exports.idRoot = ['x', 'y'];

exports.idRegex = constants.idRegex;

exports.attrRegex = constants.attrRegex;

exports.attributes = require('./attributes');

exports.transitionAxes = require('./transition_axes');

exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
    var cdSubplot, cd, trace, i, j, k;

    var fullLayout = gd._fullLayout,
        subplots = Plots.getSubplotIds(fullLayout, 'cartesian'),
        calcdata = gd.calcdata,
        modules = fullLayout._modules;

    if(!Array.isArray(traces)) {
      // If traces is not provided, then it's a complete replot and missing
      // traces are removed
        traces = [];
        for(i = 0; i < calcdata.length; i++) {
            traces.push(i);
        }
    }

    for(i = 0; i < subplots.length; i++) {
        var subplot = subplots[i],
            subplotInfo = fullLayout._plots[subplot];

        // Get all calcdata for this subplot:
        cdSubplot = [];
        var pcd;
        for(j = 0; j < calcdata.length; j++) {
            cd = calcdata[j];
            trace = cd[0].trace;

            // Skip trace if whitelist provided and it's not whitelisted:
            // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
            if(trace.xaxis + trace.yaxis === subplot) {
                // If this trace is specifically requested, add it to the list:
                if(traces.indexOf(trace.index) !== -1) {
                    // Okay, so example: traces 0, 1, and 2 have fill = tonext. You animate
                    // traces 0 and 2. Trace 1 also needs to be updated, otherwise its fill
                    // is outdated. So this retroactively adds the previous trace if the
                    // traces are interdependent.
                    if(pcd &&
                            ['tonextx', 'tonexty', 'tonext'].indexOf(trace.fill) !== -1 &&
                            cdSubplot.indexOf(pcd) === -1) {
                        cdSubplot.push(pcd);
                    }

                    cdSubplot.push(cd);
                }

                // Track the previous trace on this subplot for the retroactive-add step
                // above:
                pcd = cd;
            }
        }

        // remove old traces, then redraw everything
        // TODO: scatterlayer is manually excluded from this since it knows how
        // to update instead of fully removing and redrawing every time. The
        // remaining plot traces should also be able to do this. Once implemented,
        // we won't need this - which should sometimes be a big speedup.
        if(subplotInfo.plot) {
            subplotInfo.plot.selectAll('g:not(.scatterlayer)').selectAll('g.trace').remove();
        }

        // Plot all traces for each module at once:
        for(j = 0; j < modules.length; j++) {
            var _module = modules[j];

            // skip over non-cartesian trace modules
            if(_module.basePlotModule.name !== 'cartesian') continue;

            // plot all traces of this type on this subplot at once
            var cdModule = [];
            for(k = 0; k < cdSubplot.length; k++) {
                cd = cdSubplot[k];
                trace = cd[0].trace;

                if((trace._module === _module) && (trace.visible === true)) {
                    cdModule.push(cd);
                }
            }

            _module.plot(gd, subplotInfo, cdModule, transitionOpts, makeOnCompleteCallback);
        }
    }
};

exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
    var oldModules = oldFullLayout._modules || [],
        newModules = newFullLayout._modules || [];

    var hadScatter, hasScatter, i;

    for(i = 0; i < oldModules.length; i++) {
        if(oldModules[i].name === 'scatter') {
            hadScatter = true;
            break;
        }
    }

    for(i = 0; i < newModules.length; i++) {
        if(newModules[i].name === 'scatter') {
            hasScatter = true;
            break;
        }
    }

    if(hadScatter && !hasScatter) {
        var oldPlots = oldFullLayout._plots,
            ids = Object.keys(oldPlots || {});

        for(i = 0; i < ids.length; i++) {
            var subplotInfo = oldPlots[ids[i]];

            if(subplotInfo.plot) {
                subplotInfo.plot.select('g.scatterlayer')
                    .selectAll('g.trace')
                    .remove();
            }
        }
    }

    var hadCartesian = (oldFullLayout._has && oldFullLayout._has('cartesian'));
    var hasCartesian = (newFullLayout._has && newFullLayout._has('cartesian'));

    if(hadCartesian && !hasCartesian) {
        var subplotLayers = oldFullLayout._cartesianlayer.selectAll('.subplot');

        subplotLayers.call(purgeSubplotLayers, oldFullLayout);
        oldFullLayout._defs.selectAll('.axesclip').remove();
    }
};

exports.drawFramework = function(gd) {
    var fullLayout = gd._fullLayout,
        subplotData = makeSubplotData(gd);

    var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot')
        .data(subplotData, Lib.identity);

    subplotLayers.enter().append('g')
        .attr('class', function(name) { return 'subplot ' + name; });

    subplotLayers.order();

    subplotLayers.exit()
        .call(purgeSubplotLayers, fullLayout);

    subplotLayers.each(function(name) {
        var plotinfo = fullLayout._plots[name];

        // keep ref to plot group
        plotinfo.plotgroup = d3.select(this);

        // initialize list of overlay subplots
        plotinfo.overlays = [];

        makeSubplotLayer(plotinfo);

        // fill in list of overlay subplots
        if(plotinfo.mainplot) {
            var mainplot = fullLayout._plots[plotinfo.mainplot];
            mainplot.overlays.push(plotinfo);
        }

        // make separate drag layers for each subplot,
        // but append them to paper rather than the plot groups,
        // so they end up on top of the rest
        plotinfo.draglayer = joinLayer(fullLayout._draggers, 'g', name);
    });
};

function makeSubplotData(gd) {
    var fullLayout = gd._fullLayout,
        subplots = Axes.getSubplots(gd);

    var subplotData = [],
        overlays = [];

    for(var i = 0; i < subplots.length; i++) {
        var subplot = subplots[i],
            plotinfo = fullLayout._plots[subplot];

        var xa = plotinfo.xaxis,
            ya = plotinfo.yaxis;

        // is this subplot overlaid on another?
        // ax.overlaying is the id of another axis of the same
        // dimension that this one overlays to be an overlaid subplot,
        // the main plot must exist make sure we're not trying to
        // overlay on an axis that's already overlaying another
        var xa2 = Axes.getFromId(gd, xa.overlaying) || xa;
        if(xa2 !== xa && xa2.overlaying) {
            xa2 = xa;
            xa.overlaying = false;
        }

        var ya2 = Axes.getFromId(gd, ya.overlaying) || ya;
        if(ya2 !== ya && ya2.overlaying) {
            ya2 = ya;
            ya.overlaying = false;
        }

        var mainplot = xa2._id + ya2._id;
        if(mainplot !== subplot && subplots.indexOf(mainplot) !== -1) {
            plotinfo.mainplot = mainplot;
            plotinfo.mainplotinfo = fullLayout._plots[mainplot];
            overlays.push(subplot);

            // for now force overlays to overlay completely... so they
            // can drag together correctly and share backgrounds.
            // Later perhaps we make separate axis domain and
            // tick/line domain or something, so they can still share
            // the (possibly larger) dragger and background but don't
            // have to both be drawn over that whole domain
            xa.domain = xa2.domain.slice();
            ya.domain = ya2.domain.slice();
        }
        else {
            subplotData.push(subplot);
        }
    }

    // main subplots before overlays
    subplotData = subplotData.concat(overlays);

    return subplotData;
}

function makeSubplotLayer(plotinfo) {
    var plotgroup = plotinfo.plotgroup,
        id = plotinfo.id;

    // Layers to keep plot types in the right order.
    // from back to front:
    // 1. heatmaps, 2D histos and contour maps
    // 2. bars / 1D histos
    // 3. errorbars for bars and scatter
    // 4. scatter
    // 5. box plots
    function joinPlotLayers(parent) {
        joinLayer(parent, 'g', 'imagelayer');
        joinLayer(parent, 'g', 'maplayer');
        joinLayer(parent, 'g', 'barlayer');
        joinLayer(parent, 'g', 'boxlayer');
        joinLayer(parent, 'g', 'scatterlayer');
    }

    if(!plotinfo.mainplot) {
        plotinfo.bg = joinLayer(plotgroup, 'rect', 'bg');
        plotinfo.bg.style('stroke-width', 0);

        var backLayer = joinLayer(plotgroup, 'g', 'layer-subplot');
        plotinfo.shapelayer = joinLayer(backLayer, 'g', 'shapelayer');
        plotinfo.imagelayer = joinLayer(backLayer, 'g', 'imagelayer');

        plotinfo.gridlayer = joinLayer(plotgroup, 'g', 'gridlayer');
        plotinfo.overgrid = joinLayer(plotgroup, 'g', 'overgrid');

        plotinfo.zerolinelayer = joinLayer(plotgroup, 'g', 'zerolinelayer');
        plotinfo.overzero = joinLayer(plotgroup, 'g', 'overzero');

        plotinfo.plot = joinLayer(plotgroup, 'g', 'plot');
        plotinfo.overplot = joinLayer(plotgroup, 'g', 'overplot');

        plotinfo.xlines = joinLayer(plotgroup, 'path', 'xlines');
        plotinfo.ylines = joinLayer(plotgroup, 'path', 'ylines');
        plotinfo.overlines = joinLayer(plotgroup, 'g', 'overlines');

        plotinfo.xaxislayer = joinLayer(plotgroup, 'g', 'xaxislayer');
        plotinfo.yaxislayer = joinLayer(plotgroup, 'g', 'yaxislayer');
        plotinfo.overaxes = joinLayer(plotgroup, 'g', 'overaxes');
    }
    else {
        var mainplotinfo = plotinfo.mainplotinfo;

        // now make the components of overlaid subplots
        // overlays don't have backgrounds, and append all
        // their other components to the corresponding
        // extra groups of their main plots.

        plotinfo.gridlayer = joinLayer(mainplotinfo.overgrid, 'g', id);
        plotinfo.zerolinelayer = joinLayer(mainplotinfo.overzero, 'g', id);

        plotinfo.plot = joinLayer(mainplotinfo.overplot, 'g', id);
        plotinfo.xlines = joinLayer(mainplotinfo.overlines, 'path', id);
        plotinfo.ylines = joinLayer(mainplotinfo.overlines, 'path', id);
        plotinfo.xaxislayer = joinLayer(mainplotinfo.overaxes, 'g', id);
        plotinfo.yaxislayer = joinLayer(mainplotinfo.overaxes, 'g', id);
    }

    // common attributes for all subplots, overlays or not
    plotinfo.plot.call(joinPlotLayers);

    plotinfo.xlines
        .style('fill', 'none')
        .classed('crisp', true);

    plotinfo.ylines
        .style('fill', 'none')
        .classed('crisp', true);
}

function purgeSubplotLayers(layers, fullLayout) {
    if(!layers) return;

    layers.each(function(subplot) {
        var plotgroup = d3.select(this),
            clipId = 'clip' + fullLayout._uid + subplot + 'plot';

        plotgroup.remove();
        fullLayout._draggers.selectAll('g.' + subplot).remove();
        fullLayout._defs.select('#' + clipId).remove();

        // do not remove individual axis <clipPath>s here
        // as other subplots may need them
    });
}

function joinLayer(parent, nodeType, className) {
    var layer = parent.selectAll('.' + className)
        .data([0]);

    layer.enter().append(nodeType)
        .classed(className, true);

    return layer;
}
<|endoftext|>


<commit_before>/**
 * @file ColGroup component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Statics
import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

// Vendors
import isEmpty from 'lodash/isEmpty';
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';

class ColGroup extends Component {

    static Fragment = TableFragment;
    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getColStyle = column => {

        const {columnKeyField, columnsWidth, useColumnsWidth, defaultColumnWidth} = this.props,
            result = {};

        // width
        result.width = useColumnsWidth ?
            (columnsWidth && columnsWidth.get(TC.getColumnKey(column, columnKeyField)))
            :
            (column.width || defaultColumnWidth);

        // min width
        result.minWidth = column.minWidth ?
            column.minWidth
            :
            result.width;

        return isEmpty(result) ? null : result;

    };

    render() {

        const {columns, ignoreColumnSpan} = this.props;

        return columns ?
            <colgroup>
                {
                    columns.map(({column, span}, index) => column ?
                        <col key={index}
                             style={this.getColStyle(column)}
                             span={ignoreColumnSpan ? null : (span && span > 1 ? span : null)}/>
                        :
                        null
                    )
                }
            </colgroup>
            :
            null;

    }

}

ColGroup.propTypes = {

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * unique keyof column.
         */
        key: PropTypes.string,

        /**
         * fixed position of column ( 'left' / 'right' )
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * align of current column
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,
    columnKeyField: PropTypes.string,
    columnsWidth: PropTypes.object,
    useColumnsWidth: PropTypes.bool,

    /**
     * column resizable
     */
    isColumnResizable: PropTypes.bool,
    defaultColumnWidth: PropTypes.number,
    minColumnWidth: PropTypes.number,

    ignoreColumnSpan: PropTypes.bool

};

ColGroup.defaultProps = {

    columnKeyField: 'key',
    useColumnsWidth: false,

    /**
     * column resizable
     */
    isColumnResizable: false,
    defaultColumnWidth: 100,
    minColumnWidth: 64,

    ignoreColumnSpan: false

};

export default ColGroup;
<commit_msg>update ColGroup<commit_after>/**
 * @file ColGroup component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Statics
import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

// Vendors
import isEmpty from 'lodash/isEmpty';
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';

class ColGroup extends Component {

    static Fragment = TableFragment;
    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getColStyle = column => {

        const {columnKeyField, columnsWidth, useColumnsWidth, defaultColumnWidth, minColumnWidth} = this.props,
            result = {};

        // width
        result.width = useColumnsWidth ?
            (columnsWidth && columnsWidth.get(TC.getColumnKey(column, columnKeyField)))
            :
            (column.width || defaultColumnWidth);

        // min width
        result.minWidth = column.minWidth ?
            column.minWidth
            :
            (minColumnWidth || result.width);

        return isEmpty(result) ? null : result;

    };

    render() {

        const {columns, ignoreColumnSpan} = this.props;

        return columns ?
            <colgroup>
                {
                    columns.map(({column, span}, index) => column ?
                        <col key={index}
                             style={this.getColStyle(column)}
                             span={ignoreColumnSpan ? null : (span && span > 1 ? span : null)}/>
                        :
                        null
                    )
                }
            </colgroup>
            :
            null;

    }

}

ColGroup.propTypes = {

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * unique keyof column.
         */
        key: PropTypes.string,

        /**
         * fixed position of column ( 'left' / 'right' )
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * align of current column
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,
    columnKeyField: PropTypes.string,
    columnsWidth: PropTypes.object,
    useColumnsWidth: PropTypes.bool,

    /**
     * column resizable
     */
    isColumnResizable: PropTypes.bool,
    defaultColumnWidth: PropTypes.number,
    minColumnWidth: PropTypes.number,

    ignoreColumnSpan: PropTypes.bool

};

ColGroup.defaultProps = {

    columnKeyField: 'key',
    useColumnsWidth: false,

    /**
     * column resizable
     */
    isColumnResizable: false,
    defaultColumnWidth: 100,
    minColumnWidth: 64,

    ignoreColumnSpan: false

};

export default ColGroup;
<|endoftext|>


<commit_before>window.Schedule = function (scheduleContainer, options) {
  var self = this;

  var NUM_COLORS        = 7;
  var TEXT_COLORS       = ['#d1265d', '#1577aa', '#bf8a2e', '#008a2e', '#853d80', '#9d5733', '#d9652b'];
  var BACKGROUND_COLORS = ['#ffd4df', '#ceeffc', '#fff4d0', '#dcf7da', '#f7e2f7', '#ede6df', '#ffe9cf'];
  var BORDER_COLORS     = ['#ff2066', '#00aff2', '#ffcb45', '#48da58', '#d373da', '#a48363', '#ff9332'];
  var SELECTED_COLORS   = ['#ff3575', '#19b5f2', '#ffcf56', '#59dc68', '#d57fdd', '#ac8f71', '#ff9c46'];
  // /*                         PINK       BLUE       YELLOW     GREEN      PURPLE     BROWN      ORANGE */

  // var NUM_COLORS        = 6;
  // var TEXT_COLORS       = ['#720', '#722', '#661', '#227', '#166', '#616'];
  // var BACKGROUND_COLORS = ['#fdc', '#edd', '#eed', '#dde', '#dee', '#ede'];
  // var BORDER_COLORS     = ['#b62', '#b44', '#994', '#448', '#499', '#949'];

  options = options || {};
  options.daySpan   = options.daySpan   || 5;
  options.dayBegin  = options.dayBegin  || 1;
  options.gridSize  = options.gridSize  || 60;
  options.timeSpan  = Math.ceil((options.timeSpan  || 720) / 60) * 60;
  options.timeBegin = Math.ceil((options.timeBegin || 480) / 60) * 60;

  var scheduleElement = document.createElement('schedule-view');
  var legendElement   = document.createElement('schedule-legend');
  var gridElement     = document.createElement('schedule-grid');

  scheduleElement.appendChild(legendElement);
  scheduleElement.appendChild(gridElement);
  scheduleContainer.appendChild(scheduleElement);

  var daySize = function (n) {
    return n * (100 / options.daySpan) + '%';
  };

  var timeSize = function (n) {
    return n * (100 / options.timeSpan) + '%';
  };

  self.addEvent = function (event) {
    var eventText       = document.createElement('event-text');
    var eventElement    = document.createElement('schedule-event');
    var eventBackground = document.createElement('event-background');
    var colorIndex      = event.colorNum % NUM_COLORS;

    eventText.innerHTML                   = event.title.join('
');
    eventText.style.color                 = TEXT_COLORS[colorIndex];
    eventElement.style.top                = timeSize(event.start - options.timeBegin);
    eventElement.style.left               = daySize(event.day - options.dayBegin);
    eventElement.style.width              = 'calc(' + daySize(1) + ' - 6px)';
    eventElement.style.height             = 'calc(' + timeSize(event.end - event.start) + ' - 2px)';
    eventElement.style.borderColor        = BORDER_COLORS[colorIndex];
    eventBackground.style.backgroundColor = BACKGROUND_COLORS[colorIndex];

    if("tooltip" in event) {
      eventElement.title = event.tooltip;
    }

    eventElement.appendChild(eventBackground);
    eventElement.appendChild(eventText);
    scheduleElement.appendChild(eventElement);
  };

  self.clearEvents = function () {
    var events = scheduleElement.querySelectorAll('schedule-event');
    for (var e = 0; e < events.length; ++e)
      events[e].parentNode.removeChild(events[e]);
  };

  self.setEvents = function (events) {
    self.clearEvents();
    events.forEach(function (event) {
      self.addEvent(event);
    });
  };

  self.destroy = function () {
    scheduleContainer.removeChild(scheduleElement);
  };

  var drawLegend = function () {
    for (var r = 1; r < options.timeSpan / 60; ++r) {
      var hourElement = document.createElement('legend-hour');
      var hour = options.timeBegin / 60 + r;

      if      (hour == 0)  hour = '12 AM';
      else if (hour == 12) hour = 'Noon';
      else if (hour < 12)  hour = hour + ' AM';
      else                 hour = hour - 12 + ' PM';

      hourElement.textContent = hour;
      hourElement.style.top = 'calc(' + timeSize(60 * r) + ' - 0.75em)';
      legendElement.appendChild(hourElement);
    }
  };

  var drawGrid = function () {
    for (var d = 0; d < options.daySpan; ++d) {
      var dayElement = document.createElement('grid-day');
      dayElement.style.width = daySize(1);

      for (var r = 0; r < options.timeSpan / options.gridSize; ++r) {
        var hourElement = document.createElement('grid-hour');
        hourElement.style.height = timeSize(options.gridSize);
        dayElement.appendChild(hourElement);
      }

      gridElement.appendChild(dayElement);
    }
  };

  drawLegend();
  drawGrid();
};
<commit_msg>Added if space and changed double quotes to single<commit_after>window.Schedule = function (scheduleContainer, options) {
  var self = this;

  var NUM_COLORS        = 7;
  var TEXT_COLORS       = ['#d1265d', '#1577aa', '#bf8a2e', '#008a2e', '#853d80', '#9d5733', '#d9652b'];
  var BACKGROUND_COLORS = ['#ffd4df', '#ceeffc', '#fff4d0', '#dcf7da', '#f7e2f7', '#ede6df', '#ffe9cf'];
  var BORDER_COLORS     = ['#ff2066', '#00aff2', '#ffcb45', '#48da58', '#d373da', '#a48363', '#ff9332'];
  var SELECTED_COLORS   = ['#ff3575', '#19b5f2', '#ffcf56', '#59dc68', '#d57fdd', '#ac8f71', '#ff9c46'];
  // /*                         PINK       BLUE       YELLOW     GREEN      PURPLE     BROWN      ORANGE */

  // var NUM_COLORS        = 6;
  // var TEXT_COLORS       = ['#720', '#722', '#661', '#227', '#166', '#616'];
  // var BACKGROUND_COLORS = ['#fdc', '#edd', '#eed', '#dde', '#dee', '#ede'];
  // var BORDER_COLORS     = ['#b62', '#b44', '#994', '#448', '#499', '#949'];

  options = options || {};
  options.daySpan   = options.daySpan   || 5;
  options.dayBegin  = options.dayBegin  || 1;
  options.gridSize  = options.gridSize  || 60;
  options.timeSpan  = Math.ceil((options.timeSpan  || 720) / 60) * 60;
  options.timeBegin = Math.ceil((options.timeBegin || 480) / 60) * 60;

  var scheduleElement = document.createElement('schedule-view');
  var legendElement   = document.createElement('schedule-legend');
  var gridElement     = document.createElement('schedule-grid');

  scheduleElement.appendChild(legendElement);
  scheduleElement.appendChild(gridElement);
  scheduleContainer.appendChild(scheduleElement);

  var daySize = function (n) {
    return n * (100 / options.daySpan) + '%';
  };

  var timeSize = function (n) {
    return n * (100 / options.timeSpan) + '%';
  };

  self.addEvent = function (event) {
    var eventText       = document.createElement('event-text');
    var eventElement    = document.createElement('schedule-event');
    var eventBackground = document.createElement('event-background');
    var colorIndex      = event.colorNum % NUM_COLORS;

    eventText.innerHTML                   = event.title.join('
');
    eventText.style.color                 = TEXT_COLORS[colorIndex];
    eventElement.style.top                = timeSize(event.start - options.timeBegin);
    eventElement.style.left               = daySize(event.day - options.dayBegin);
    eventElement.style.width              = 'calc(' + daySize(1) + ' - 6px)';
    eventElement.style.height             = 'calc(' + timeSize(event.end - event.start) + ' - 2px)';
    eventElement.style.borderColor        = BORDER_COLORS[colorIndex];
    eventBackground.style.backgroundColor = BACKGROUND_COLORS[colorIndex];

    if ('tooltip' in event) {
      eventElement.title = event.tooltip;
    }

    eventElement.appendChild(eventBackground);
    eventElement.appendChild(eventText);
    scheduleElement.appendChild(eventElement);
  };

  self.clearEvents = function () {
    var events = scheduleElement.querySelectorAll('schedule-event');
    for (var e = 0; e < events.length; ++e)
      events[e].parentNode.removeChild(events[e]);
  };

  self.setEvents = function (events) {
    self.clearEvents();
    events.forEach(function (event) {
      self.addEvent(event);
    });
  };

  self.destroy = function () {
    scheduleContainer.removeChild(scheduleElement);
  };

  var drawLegend = function () {
    for (var r = 1; r < options.timeSpan / 60; ++r) {
      var hourElement = document.createElement('legend-hour');
      var hour = options.timeBegin / 60 + r;

      if      (hour == 0)  hour = '12 AM';
      else if (hour == 12) hour = 'Noon';
      else if (hour < 12)  hour = hour + ' AM';
      else                 hour = hour - 12 + ' PM';

      hourElement.textContent = hour;
      hourElement.style.top = 'calc(' + timeSize(60 * r) + ' - 0.75em)';
      legendElement.appendChild(hourElement);
    }
  };

  var drawGrid = function () {
    for (var d = 0; d < options.daySpan; ++d) {
      var dayElement = document.createElement('grid-day');
      dayElement.style.width = daySize(1);

      for (var r = 0; r < options.timeSpan / options.gridSize; ++r) {
        var hourElement = document.createElement('grid-hour');
        hourElement.style.height = timeSize(options.gridSize);
        dayElement.appendChild(hourElement);
      }

      gridElement.appendChild(dayElement);
    }
  };

  drawLegend();
  drawGrid();
};
<|endoftext|>


<commit_before>// --
// OTRS.Customer.js - provides functions for the customer login
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: OTRS.App.Customer.js,v 1.10 2010-05-11 13:33:50 fn Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var OTRS = OTRS || {};
OTRS.App = OTRS.App || {};

/**
 * @namespace
 * @exports TargetNS as OTRS.App.Customer
 * @description
 *      This namespace contains all form functions.
 */
OTRS.App.Customer = (function (TargetNS) {
    /**
     * @function
     * @description
     *      This function initializes the login functions.
     *      Time gets tracked in an hidden field.
     *      In the login we have for steps:
     *      1. input field gets focused -> label gets greyed out via class="Focused"
     *      2. something is typed -> label gets hidden
     *      3. user leaves input field -> if the field is blank the label gets shown again, 'focused' class gets removed
     *      4. first input field gets focused
     */
    TargetNS.InitLogin = function() {
        var $Inputs = $('input').not(':checkbox, :hidden, :radio'),
            Now = new Date(),
            Diff = Now.getTimezoneOffset(),
            $Label;

        $('#TimeOffset').val(Diff);

        $Inputs
            .focus(function(){
                $Label = $(this).prev('label');
                $(this).prev('label').addClass('Focused');
                if ($(this).val()) $Label.hide();
            })
            .bind('keyup change', function(){
                ToggleLabel(this);
            })
            .blur(function(){
                $Label = $(this).prev('label');
                if (!$(this).val()) $Label.show();
                $Label.removeClass('Focused');
            })
            .first().focus();
        CheckInputs($Inputs);
    };

    /**
     * @function
     * @param {DOMObject} $PopulatedInput is a filled out input filled
     * @description
     *      This function hides the label of the given field if there is value in the field.
     *      If there is no value in the given field the label is made visible.
     */

    function ToggleLabel(PopulatedInput) {
        var $PopulatedInput = $(PopulatedInput),
            $Label = $PopulatedInput.prev('label');
        if ($PopulatedInput.val() != "") {
            $Label.hide();
        }
        else {
            $Label.show();
        }
    };

    /**
     * @function
     * @param {jQueryObject} $Inputs is an object containing input fields
     * @description
     *      This function is used initially and hides labels of
     *      already filled out input fields (auto population of browsers)
     *      and focuses on the first next 'non-filled-out' input field.
     */
    function CheckInputs($Inputs){
        var LastFilledElement = 0;
        $.each($Inputs, function(Index, Input) {
            if($(Input).val()){
                ToggleLabel(Input);
                LastFilledElement = Index;
            }
        });
        if (LastFilledElement != 0) {
            $Inputs[LastFilledElement + 1].focus();
        }
    }

    /**
     * @function
     * @description
     *      This function makes the whole row in the MyTickets and CompanyTickets view clickable.
     */

    TargetNS.ClickableRow = function(){
        $("table tr").click(function(){
            window.location.href = $("a", this).attr("href");
        });
    };

    /**
     * @function
     * @description
     *      This function adds the class 'Js' to the 'Body' div to enhance the interface (clickable rows).
     */
    TargetNS.Enhance = function(){
        $('body').addClass('Js');
    }

    /**
     * @function
     * @description
     *      This function binds functions to the 'MessageHeader' and the 'Reply' button
     *      to toggle the visibility of the MessageBody and the reply form.
     *      Also it checks the iframes to resize them to their full (inner) size
     *      and hides the quotes inside the iframes + adds an anchor to toggle the visibility of the quotes
     */
    TargetNS.InitTicketZoom = function(){
        var $Messages = $('#Messages > li'),
            $VisibleMessage = $Messages.last().removeClass('Visible'),
            $MessageHeaders = $('.MessageHeader', $Messages);

        $MessageHeaders.click(function(Event){
            ToggleMessage($(this).parent());
            Event.preventDefault();
        });
        $('#ReplyButton').click(function(Event){
            Event.preventDefault();
            var $FollowUp = $(this).parent().toggleClass('Visible');
            $('html').css({scrollTop: $('#Body').height()});
            RichTextFocus();
        });
        /* correct the status saved in the hidden field of the initial visible message */
        $LastMessageStatus = $('> input[name=ArticleState]', $VisibleMessage);
        LoadMessage($($VisibleMessage), $LastMessageStatus);
    }

    /**
     * @function
     * @description
     *      This function checkes the value of a hidden input field containing the state of the article:
     *      untouched (= not yet loaded), true or false. If the article is allready loaded (-> true), and
     *      user calles this function by clicking on the messagehead, the article gets hidden by removing
     *      the class 'Visible' and the status changes to false. If the messagehead is clicked while the
     *      status is false (e.g. the article is hidden), the article gets the class 'Visible' again and
     *      the status gets changed to true.
     */

    function ToggleMessage($Message){
        var $Status = $('> input[name=ArticleState]', $Message);
        switch ($Status.val()){
            case "untouched":
                LoadMessage($Message, $Status);
            break;
            case "true":
                $Message.removeClass('Visible');
                $Status.val("false");
            break;
            case "false":
                $Message.addClass('Visible');
                $Status.val("true");
            break;
        }
    }

    /**
     * @function
     * @description
     *      This function is called when an articles should be loaded. Our trick is, to hide the
     *      url of a containing iframe in the title attribute of the iframe so that it doesn't load
     *      immediately when the site loads. So we set the url in this function.
     */

    function LoadMessage($Message, $Status){
        var $SubjectHolder = $('h3 span', $Message),
            Subject = $SubjectHolder.text(),
            LoadingString = $SubjectHolder.attr('title'),
            $Iframe = $('iframe', $Message),
            Source = $Iframe.attr('title');

        /*  Change Subject to Loading */
        $SubjectHolder.text(LoadingString);

        /*  Load iframe -> get title and put it in src */
        if(Source != 'about:blank') $Iframe.attr('src', Source);

        var callback = function(){
            /*  Set StateStorage to true */
            $Status.val('true');

            /*  Show MessageContent -> add class Visible */
            $Message.addClass('Visible');

            /*  Change Subject back from Loading */
            $SubjectHolder.text(Subject).attr('title', Subject);
        }

        /*  Hide quotes and resize -> HideQuote(Iframe) */
        CheckIframe($Iframe, callback);
    }

    /**
     * @function
     * @param {DOMObject} an iframe
     * @description
     *      This function contains some workarounds for all browsers to get resize the iframe
     * @see http://sonspring.com/journal/jquery-iframe-sizing
     */
    function CheckIframe(Iframe, callback){
        if ($.browser.safari || $.browser.opera){
            $(Iframe).load(function(){
                setTimeout(HideQuote, 0, this, callback);
            });
            var Source = Iframe.src;
            Iframe.src = '';
            Iframe.src = Source;
        }
        else {
            $(Iframe).load(function(){
                HideQuote(this, callback);
            });
        }
    }

    /**
     * @function
     * @param {DOMObject} an iframe
     * @description
     *      finds the quote in an iframe (type=cite), hides it and
     *      adds an anchor in front of the hidden quote to toggle the visibility of the quote
     */

    function HideQuote(Iframe, callback){
        $(Iframe)
            .contents().find('[type=cite]').hide()
            .before('Show quoted text')
            // add a toggle listener to the anchor (the prev element we just added)
            .prev().toggle(
                function(){ // show quote, change anchor name, recalculate iframe height
                    $(this).text("Hide quoted text").next().show();
                    CalculateHeight(Iframe);
                },
                function(){ // hide quote, change anchor name, recalculate iframe height
                    $(this).text("Show quoted text").next().hide();
                    setTimeout(CalculateHeight, 200, Iframe);
                }
            );
        // initial height calculation
        CalculateHeight(Iframe);
        if(callback) callback();
    }

    /**
     * @function
     * @param {DOMObject} an iframe
     * @description
     *      sets the size of the iframe to the size of its inner html
     *      .contents accesses the iframe to get its height
     */

    function CalculateHeight(Iframe){
        var Newheight = $(Iframe).contents().find('html').outerHeight();
        if(Newheight > 2500) Newheight = 2500;
        $(Iframe).height(Newheight);
    }

    return TargetNS;
}(OTRS.App.Customer || {}));<commit_msg>TicketZoom Javascript code updated: function for the new FollowUp close button and improved handling of the first shown iframe.<commit_after>// --
// OTRS.Customer.js - provides functions for the customer login
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: OTRS.App.Customer.js,v 1.11 2010-05-12 12:54:40 fn Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var OTRS = OTRS || {};
OTRS.App = OTRS.App || {};

/**
 * @namespace
 * @exports TargetNS as OTRS.App.Customer
 * @description
 *      This namespace contains all form functions.
 */
OTRS.App.Customer = (function (TargetNS) {
    /**
     * @function
     * @description
     *      This function initializes the login functions.
     *      Time gets tracked in an hidden field.
     *      In the login we have for steps:
     *      1. input field gets focused -> label gets greyed out via class="Focused"
     *      2. something is typed -> label gets hidden
     *      3. user leaves input field -> if the field is blank the label gets shown again, 'focused' class gets removed
     *      4. first input field gets focused
     */
    TargetNS.InitLogin = function() {
        var $Inputs = $('input').not(':checkbox, :hidden, :radio'),
            Now = new Date(),
            Diff = Now.getTimezoneOffset(),
            $Label;

        $('#TimeOffset').val(Diff);

        $Inputs
            .focus(function(){
                $Label = $(this).prev('label');
                $(this).prev('label').addClass('Focused');
                if ($(this).val()) $Label.hide();
            })
            .bind('keyup change', function(){
                ToggleLabel(this);
            })
            .blur(function(){
                $Label = $(this).prev('label');
                if (!$(this).val()) $Label.show();
                $Label.removeClass('Focused');
            })
            .first().focus();
        CheckInputs($Inputs);
    };

    /**
     * @function
     * @param {DOMObject} $PopulatedInput is a filled out input filled
     * @description
     *      This function hides the label of the given field if there is value in the field.
     *      If there is no value in the given field the label is made visible.
     */

    function ToggleLabel(PopulatedInput) {
        var $PopulatedInput = $(PopulatedInput),
            $Label = $PopulatedInput.prev('label');
        if ($PopulatedInput.val() != "") {
            $Label.hide();
        }
        else {
            $Label.show();
        }
    };

    /**
     * @function
     * @param {jQueryObject} $Inputs is an object containing input fields
     * @description
     *      This function is used initially and hides labels of
     *      already filled out input fields (auto population of browsers)
     *      and focuses on the first next 'non-filled-out' input field.
     */
    function CheckInputs($Inputs){
        var LastFilledElement = 0;
        $.each($Inputs, function(Index, Input) {
            if($(Input).val()){
                ToggleLabel(Input);
                LastFilledElement = Index;
            }
        });
        if (LastFilledElement != 0) {
            $Inputs[LastFilledElement + 1].focus();
        }
    }

    /**
     * @function
     * @description
     *      This function makes the whole row in the MyTickets and CompanyTickets view clickable.
     */

    TargetNS.ClickableRow = function(){
        $("table tr").click(function(){
            window.location.href = $("a", this).attr("href");
        });
    };

    /**
     * @function
     * @description
     *      This function adds the class 'Js' to the 'Body' div to enhance the interface (clickable rows).
     */
    TargetNS.Enhance = function(){
        $('body').addClass('Js');
    }

    /**
     * @function
     * @description
     *      This function binds functions to the 'MessageHeader' and the 'Reply' button
     *      to toggle the visibility of the MessageBody and the reply form.
     *      Also it checks the iframes to resize them to their full (inner) size
     *      and hides the quotes inside the iframes + adds an anchor to toggle the visibility of the quotes
     */
    TargetNS.InitTicketZoom = function(){
        var $Messages = $('#Messages > li'),
            $VisibleMessage = $Messages.last(),
            $VisibleIframe = $('#VisibleFrame'),
            $MessageHeaders = $('.MessageHeader', $Messages),
            $FollowUp = $('#FollowUp'),
            $RTE = $('#RichText');

        $MessageHeaders.click(function(Event){
            ToggleMessage($(this).parent());
            Event.preventDefault();
        });
        $('#ReplyButton').click(function(Event){
            Event.preventDefault();
            $FollowUp.addClass('Visible');
            $('html').css({scrollTop: $('#Body').height()});
            OTRS.UI.RichTextEditor.Focus($RTE);
        });
        $('#CloseButton').click(function(Event){
            Event.preventDefault();
            $FollowUp.removeClass('Visible');
            $('html').css({scrollTop: $('#Body').height()});
        });
        /* correct the status saved in the hidden field of the initial visible message */
        $LastMessageStatus = $('> input[name=ArticleState]', $VisibleMessage).val("true");
        HideQuote($VisibleIframe);
    }

    /**
     * @function
     * @description
     *      This function checkes the value of a hidden input field containing the state of the article:
     *      untouched (= not yet loaded), true or false. If the article is allready loaded (-> true), and
     *      user calles this function by clicking on the messagehead, the article gets hidden by removing
     *      the class 'Visible' and the status changes to false. If the messagehead is clicked while the
     *      status is false (e.g. the article is hidden), the article gets the class 'Visible' again and
     *      the status gets changed to true.
     */

    function ToggleMessage($Message){
        var $Status = $('> input[name=ArticleState]', $Message);
        switch ($Status.val()){
            case "untouched":
                LoadMessage($Message, $Status);
            break;
            case "true":
                $Message.removeClass('Visible');
                $Status.val("false");
            break;
            case "false":
                $Message.addClass('Visible');
                $Status.val("true");
            break;
        }
    }

    /**
     * @function
     * @description
     *      This function is called when an articles should be loaded. Our trick is, to hide the
     *      url of a containing iframe in the title attribute of the iframe so that it doesn't load
     *      immediately when the site loads. So we set the url in this function.
     */

    function LoadMessage($Message, $Status){
        var $SubjectHolder = $('h3 span', $Message),
            Subject = $SubjectHolder.text(),
            LoadingString = $SubjectHolder.attr('title'),
            $Iframe = $('iframe', $Message),
            Source = $Iframe.attr('title');

        /*  Change Subject to Loading */
        $SubjectHolder.text(LoadingString);

        /*  Load iframe -> get title and put it in src */
        if(Source != 'about:blank') $Iframe.attr('src', Source);

        var callback = function(){
            /*  Set StateStorage to true */
            $Status.val('true');

            /*  Show MessageContent -> add class Visible */
            $Message.addClass('Visible');

            /*  Change Subject back from Loading */
            $SubjectHolder.text(Subject).attr('title', Subject);
        }

        CheckIframe($Iframe, callback);
    }

    /**
     * @function
     * @param {DOMObject} an iframe
     * @description
     *      This function contains some workarounds for all browsers to get resize the iframe
     * @see http://sonspring.com/journal/jquery-iframe-sizing
     */
    function CheckIframe(Iframe, callback){
        if ($.browser.safari || $.browser.opera){
            $(Iframe).load(function(){
                setTimeout(HideQuote, 0, this, callback);
            });
            var Source = Iframe.src;
            Iframe.src = '';
            Iframe.src = Source;
        }
        else {
            $(Iframe).load(function(){
                HideQuote(this, callback);
            });
        }
    }

    /**
     * @function
     * @param {DOMObject} an iframe
     * @description
     *      finds the quote in an iframe (type=cite), hides it and
     *      adds an anchor in front of the hidden quote to toggle the visibility of the quote
     */

    function HideQuote(Iframe, callback){
        $(Iframe)
            .contents().find('[type=cite]').hide()
            .before('Show quoted text')
            // add a toggle listener to the anchor (the prev element we just added)
            .prev().toggle(
                function(){ // show quote, change anchor name, recalculate iframe height
                    $(this).text("Hide quoted text").next().show();
                    CalculateHeight(Iframe);
                },
                function(){ // hide quote, change anchor name, recalculate iframe height
                    $(this).text("Show quoted text").next().hide();
                    setTimeout(CalculateHeight, 200, Iframe);
                }
            );
        // initial height calculation
        CalculateHeight(Iframe);
        if(callback) callback();
    }

    /**
     * @function
     * @param {DOMObject} an iframe
     * @description
     *      sets the size of the iframe to the size of its inner html
     *      .contents accesses the iframe to get its height
     */

    function CalculateHeight(Iframe){
        var NewHeight = $(Iframe).contents().find('html').outerHeight();
        if(NewHeight > 2500) NewHeight = 2500;
        $(Iframe).height(NewHeight);
    }

    return TargetNS;
}(OTRS.App.Customer || {}));<|endoftext|>


<commit_before>goog.provide('ol.geom.SimpleGeometry');

goog.require('goog.asserts');
goog.require('goog.functions');
goog.require('goog.object');
goog.require('ol.extent');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.flat');

/**
 * @constructor
 * @extends {ol.geom.Geometry}
 */
ol.geom.SimpleGeometry = function() {

  goog.base(this);

  /**
   * @protected
   * @type {ol.geom.GeometryLayout}
   */
  this.layout = ol.geom.GeometryLayout.XY;

  /**
   * @protected
   * @type {number}
   */
  this.stride = 2;

  /**
   * @protected
   * @type {Array.<number>}
   */
  this.flatCoordinates = null;

};
goog.inherits(ol.geom.SimpleGeometry, ol.geom.Geometry);

/**
 * @param {number} stride Stride.
 * @private
 * @return {ol.geom.GeometryLayout} layout Layout.
 */
ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
  if (stride == 2) {
    return ol.geom.GeometryLayout.XY;
  } else if (stride == 3) {
    return ol.geom.GeometryLayout.XYZ;
  } else if (stride == 4) {
    return ol.geom.GeometryLayout.XYZM;
  } else {
    throw new Error('unsupported stride: ' + stride);
  }
};

/**
 * @param {ol.geom.GeometryLayout} layout Layout.
 * @private
 * @return {number} Stride.
 */
ol.geom.SimpleGeometry.getStrideForLayout_ = function(layout) {
  if (layout == ol.geom.GeometryLayout.XY) {
    return 2;
  } else if (layout == ol.geom.GeometryLayout.XYZ) {
    return 3;
  } else if (layout == ol.geom.GeometryLayout.XYM) {
    return 3;
  } else if (layout == ol.geom.GeometryLayout.XYZM) {
    return 4;
  } else {
    throw new Error('unsupported layout: ' + layout);
  }
};

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.containsXY = goog.functions.FALSE;

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.getExtent = function(opt_extent) {
  if (this.extentRevision != this.getRevision()) {
    this.extent = ol.extent.createOrUpdateFromFlatCoordinates(
        this.flatCoordinates, this.stride, this.extent);
    this.extentRevision = this.getRevision();
  }
  goog.asserts.assert(goog.isDef(this.extent));
  return ol.extent.returnOrUpdate(this.extent, opt_extent);
};

/**
 * @return {Array.<number>} Flat coordinates.
 */
ol.geom.SimpleGeometry.prototype.getFlatCoordinates = function() {
  return this.flatCoordinates;
};

/**
 * @return {ol.geom.GeometryLayout} Layout.
 */
ol.geom.SimpleGeometry.prototype.getLayout = function() {
  return this.layout;
};

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry =
    function(squaredTolerance) {
  if (this.simplifiedGeometryRevision != this.getRevision()) {
    goog.object.clear(this.simplifiedGeometryCache);
    this.simplifiedGeometryMaxMinSquaredTolerance = 0;
    this.simplifiedGeometryRevision = this.getRevision();
  }
  // If squaredTolerance is negative or if we know that simplification will not
  // have any effect then just return this.
  if (squaredTolerance < 0 ||
      (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
       squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
    return this;
  }
  var key = squaredTolerance.toString();
  if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
    return this.simplifiedGeometryCache[key];
  } else {
    var simplifiedGeometry =
        this.getSimplifiedGeometryInternal(squaredTolerance);
    var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
    if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
      this.simplifiedGeometryCache[key] = simplifiedGeometry;
      return simplifiedGeometry;
    } else {
      // Simplification did not actually remove any coordinates.  We now know
      // that any calls to getSimplifiedGeometry with a squaredTolerance less
      // than or equal to the current squaredTolerance will also not have any
      // effect.  This allows us to short circuit simplification (saving CPU
      // cycles) and prevents the cache of simplified geometries from filling
      // up with useless identical copies of this geometry (saving memory).
      this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
      return this;
    }
  }
};

/**
 * @param {number} squaredTolerance Squared tolerance.
 * @return {ol.geom.SimpleGeometry} Simplified geometry.
 * @protected
 */
ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal =
    function(squaredTolerance) {
  return this;
};

/**
 * @return {number} Stride.
 */
ol.geom.SimpleGeometry.prototype.getStride = function() {
  return this.stride;
};

/**
 * @param {ol.geom.GeometryLayout} layout Layout.
 * @param {Array.<number>} flatCoordinates Flat coordinates.
 * @protected
 */
ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal =
    function(layout, flatCoordinates) {
  this.stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
  this.layout = layout;
  this.flatCoordinates = flatCoordinates;
};

/**
 * @param {ol.geom.GeometryLayout|undefined} layout Layout.
 * @param {Array} coordinates Coordinates.
 * @param {number} nesting Nesting.
 * @protected
 */
ol.geom.SimpleGeometry.prototype.setLayout =
    function(layout, coordinates, nesting) {
  /** @type {number} */
  var stride;
  if (goog.isDef(layout)) {
    stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
  } else {
    var i;
    for (i = 0; i < nesting; ++i) {
      if (coordinates.length === 0) {
        this.layout = ol.geom.GeometryLayout.XY;
        this.stride = 2;
        return;
      } else {
        coordinates = /** @type {Array} */ (coordinates[0]);
      }
    }
    stride = (/** @type {Array} */ (coordinates)).length;
    layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
  }
  this.layout = layout;
  this.stride = stride;
};

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.transform = function(transformFn) {
  if (!goog.isNull(this.flatCoordinates)) {
    transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
    this.dispatchChangeEvent();
  }
};

/**
 * @param {ol.geom.SimpleGeometry} simpleGeometry Simple geometry.
 * @param {goog.vec.Mat4.Number} transform Transform.
 * @param {Array.<number>=} opt_dest Destination.
 * @return {Array.<number>} Transformed flat coordinates.
 */
ol.geom.transformSimpleGeometry2D =
    function(simpleGeometry, transform, opt_dest) {
  var flatCoordinates = simpleGeometry.getFlatCoordinates();
  if (goog.isNull(flatCoordinates)) {
    return null;
  } else {
    var stride = simpleGeometry.getStride();
    return ol.geom.flat.transform2D(
        flatCoordinates, stride, transform, opt_dest);
  }
};
<commit_msg>Add stability annotation to ol.geom.SimpleGeometry<commit_after>goog.provide('ol.geom.SimpleGeometry');

goog.require('goog.asserts');
goog.require('goog.functions');
goog.require('goog.object');
goog.require('ol.extent');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.flat');

/**
 * @constructor
 * @extends {ol.geom.Geometry}
 * @todo stability experimental
 */
ol.geom.SimpleGeometry = function() {

  goog.base(this);

  /**
   * @protected
   * @type {ol.geom.GeometryLayout}
   */
  this.layout = ol.geom.GeometryLayout.XY;

  /**
   * @protected
   * @type {number}
   */
  this.stride = 2;

  /**
   * @protected
   * @type {Array.<number>}
   */
  this.flatCoordinates = null;

};
goog.inherits(ol.geom.SimpleGeometry, ol.geom.Geometry);

/**
 * @param {number} stride Stride.
 * @private
 * @return {ol.geom.GeometryLayout} layout Layout.
 */
ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
  if (stride == 2) {
    return ol.geom.GeometryLayout.XY;
  } else if (stride == 3) {
    return ol.geom.GeometryLayout.XYZ;
  } else if (stride == 4) {
    return ol.geom.GeometryLayout.XYZM;
  } else {
    throw new Error('unsupported stride: ' + stride);
  }
};

/**
 * @param {ol.geom.GeometryLayout} layout Layout.
 * @private
 * @return {number} Stride.
 */
ol.geom.SimpleGeometry.getStrideForLayout_ = function(layout) {
  if (layout == ol.geom.GeometryLayout.XY) {
    return 2;
  } else if (layout == ol.geom.GeometryLayout.XYZ) {
    return 3;
  } else if (layout == ol.geom.GeometryLayout.XYM) {
    return 3;
  } else if (layout == ol.geom.GeometryLayout.XYZM) {
    return 4;
  } else {
    throw new Error('unsupported layout: ' + layout);
  }
};

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.containsXY = goog.functions.FALSE;

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.getExtent = function(opt_extent) {
  if (this.extentRevision != this.getRevision()) {
    this.extent = ol.extent.createOrUpdateFromFlatCoordinates(
        this.flatCoordinates, this.stride, this.extent);
    this.extentRevision = this.getRevision();
  }
  goog.asserts.assert(goog.isDef(this.extent));
  return ol.extent.returnOrUpdate(this.extent, opt_extent);
};

/**
 * @return {Array.<number>} Flat coordinates.
 */
ol.geom.SimpleGeometry.prototype.getFlatCoordinates = function() {
  return this.flatCoordinates;
};

/**
 * @return {ol.geom.GeometryLayout} Layout.
 * @todo stability experimental
 */
ol.geom.SimpleGeometry.prototype.getLayout = function() {
  return this.layout;
};

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry =
    function(squaredTolerance) {
  if (this.simplifiedGeometryRevision != this.getRevision()) {
    goog.object.clear(this.simplifiedGeometryCache);
    this.simplifiedGeometryMaxMinSquaredTolerance = 0;
    this.simplifiedGeometryRevision = this.getRevision();
  }
  // If squaredTolerance is negative or if we know that simplification will not
  // have any effect then just return this.
  if (squaredTolerance < 0 ||
      (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
       squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
    return this;
  }
  var key = squaredTolerance.toString();
  if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
    return this.simplifiedGeometryCache[key];
  } else {
    var simplifiedGeometry =
        this.getSimplifiedGeometryInternal(squaredTolerance);
    var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
    if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
      this.simplifiedGeometryCache[key] = simplifiedGeometry;
      return simplifiedGeometry;
    } else {
      // Simplification did not actually remove any coordinates.  We now know
      // that any calls to getSimplifiedGeometry with a squaredTolerance less
      // than or equal to the current squaredTolerance will also not have any
      // effect.  This allows us to short circuit simplification (saving CPU
      // cycles) and prevents the cache of simplified geometries from filling
      // up with useless identical copies of this geometry (saving memory).
      this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
      return this;
    }
  }
};

/**
 * @param {number} squaredTolerance Squared tolerance.
 * @return {ol.geom.SimpleGeometry} Simplified geometry.
 * @protected
 */
ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal =
    function(squaredTolerance) {
  return this;
};

/**
 * @return {number} Stride.
 */
ol.geom.SimpleGeometry.prototype.getStride = function() {
  return this.stride;
};

/**
 * @param {ol.geom.GeometryLayout} layout Layout.
 * @param {Array.<number>} flatCoordinates Flat coordinates.
 * @protected
 */
ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal =
    function(layout, flatCoordinates) {
  this.stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
  this.layout = layout;
  this.flatCoordinates = flatCoordinates;
};

/**
 * @param {ol.geom.GeometryLayout|undefined} layout Layout.
 * @param {Array} coordinates Coordinates.
 * @param {number} nesting Nesting.
 * @protected
 */
ol.geom.SimpleGeometry.prototype.setLayout =
    function(layout, coordinates, nesting) {
  /** @type {number} */
  var stride;
  if (goog.isDef(layout)) {
    stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
  } else {
    var i;
    for (i = 0; i < nesting; ++i) {
      if (coordinates.length === 0) {
        this.layout = ol.geom.GeometryLayout.XY;
        this.stride = 2;
        return;
      } else {
        coordinates = /** @type {Array} */ (coordinates[0]);
      }
    }
    stride = (/** @type {Array} */ (coordinates)).length;
    layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
  }
  this.layout = layout;
  this.stride = stride;
};

/**
 * @inheritDoc
 */
ol.geom.SimpleGeometry.prototype.transform = function(transformFn) {
  if (!goog.isNull(this.flatCoordinates)) {
    transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
    this.dispatchChangeEvent();
  }
};

/**
 * @param {ol.geom.SimpleGeometry} simpleGeometry Simple geometry.
 * @param {goog.vec.Mat4.Number} transform Transform.
 * @param {Array.<number>=} opt_dest Destination.
 * @return {Array.<number>} Transformed flat coordinates.
 */
ol.geom.transformSimpleGeometry2D =
    function(simpleGeometry, transform, opt_dest) {
  var flatCoordinates = simpleGeometry.getFlatCoordinates();
  if (goog.isNull(flatCoordinates)) {
    return null;
  } else {
    var stride = simpleGeometry.getStride();
    return ol.geom.flat.transform2D(
        flatCoordinates, stride, transform, opt_dest);
  }
};
<|endoftext|>