<commit_before>//Dialogue writer and selector module for combat sequence.
var Cwriter = (function()
{
    var timeCheck = 0;         //Current interval to wait to place a character. Changes based on special characters.
    var timeAsterisk = .75;    //Interval to use for asterisk.
    var timePeriod = .33;      //Interval to use for periods.
    var timeComma = .21;       //Interval to use for commas.
    var timeStandard = .033;   //Interval to use for all other characters.

    var text;                  //Text to display.
    var charCounter;           //Counter for characters in text being displayed.
    var timeCounter;           //Tracks time for character counting.

    var horizontalPositions;   //Positions for horizontal menu.

    var verticalPositions;     //Positions for vertical menu.

    function init()
    {
        horizontalPositions =
        [
            [100, 296],
            [356, 296],
            [100, 328],
            [356, 328],
            [100, 360],
            [356, 360]
        ]

        verticalPositions =
        [
            [100, 296],
            [100, 328],
            [100, 360]
        ]
    }

    //Set the time delays of the writer.
    function setTimes(
        _timeAsterisk,
        _timePeriod,
        _timeComma,
        _timeStandard)
    {
        timeCheck = 0;
        timeAsterisk = _timeAsterisk;
        timePeriod = _timePeriod;
        timeComma = _timeComma;
        timeStandard = _timeStandard;
    }

    //Set the text for the writer and reset counters.
    function setText(_text)
    {
        text = _text;
        charCounter = -1;           //Counter for the index of the most recent displayed character.
        timeCounter = timeAsterisk; //Counter for the time since a character was placed.
    }

    //Update the writer.
    function update(dt)
    {
        if(myKeys.keydown[myKeys.KEYBOARD.KEY_X])
        {
            skip();
        }

        //Tick.
        timeCounter += dt;

        //If time to place a new character and if there is a new character.
        if(timeCounter > timeCheck && charCounter < text.length)
        {
            //Reset counter and increment current character for next character.
            timeCounter = timeCounter - timeCheck;
            charCounter++;

            //SFX

            //Change interval for new character.
            switch(text.charAt(charCounter))
            {
                case ".":
                    Sound.pauseSound("text");
                    timeCheck = timePeriod;
                    break;
                case ",":
                    Sound.pauseSound("text");
                    timeCheck = timeComma;
                    break;
                case "*":
                    timeCheck = timeAsterisk;
                    break;
                default:
                    Sound.playSound("text", false);
                    timeCheck = timeStandard;
                    break;
            }
        }
        else
        {
            Sound.pauseSound("text");
        }
    }

    //Draw text.
    function drawText(ctx)
    {
        ctx.save();

        //Style.
        ctx.font = "24pt undertale";
        ctx.fillStyle = "#FFF";

        //Initial position.
        var textXPos = 52;
        var textYPos = 296;

        //Draw each active character, characters up to the character after the current character.
        for(var i = 0; i < charCounter + 1; i++)
        {
            //Display character if not last character and asterisk.
            if(
                text.charAt(i) != "*" ||
                text.charAt(i) != "|" ||
                i < charCounter)
            {
                ctx.fillText(
                    text.charAt(i),
                    textXPos + 2 * Math.floor(Math.random() * 1.0004),     //Random text wobble.
                    textYPos + 2 * Math.floor(Math.random() * 1.0004));
            }

            if(text.charAt(i + 1) == "|")
            {
                textXPos += ctx.measureText(text.charAt(i)).width;
                ctx.fillStyle = text.substring(i + 2, i + 6);
                i += 5;
            }
            else if(text.charAt(i + 1) == "\n") //New line moveover.
            {
                textXPos = 70;
                textYPos += 32;
            }
            else if(text.charAt(i + 1) == "*")  //Asterisk moveover
            {
                textXPos = 52;
                textYPos += 32;
            }
            else                                //Next-char moveover.
            {
                textXPos += ctx.measureText(text.charAt(i)).width;
            }
        }

        ctx.restore();
    }

    //Draw a menu.
    function drawMenu(ctx, menu, menuState, MENU_STATE)
    {
        ctx.save();

        //Style.
        ctx.font = "24pt undertale";
        ctx.fillStyle = "#FFF";

        switch(menuState)
        {
            case MENU_STATE.ACT:
                drawMenuTexts(ctx, menu, horizontalPositions);
                break;
            case MENU_STATE.ITEM:
                drawMenuTexts(ctx, menu, horizontalPositions);
                break;
            case MENU_STATE.MERCY:
                drawMenuTexts(ctx, menu, verticalPositions);
                break;
            default:
                drawMenuTexts(ctx, menu, verticalPositions);
                break;
        }

        ctx.restore();
    }

    //Draw text for all menu options.
    function drawMenuTexts(ctx, menu, positions)
    {
        for(var i = 0; i < menu.length; i++)
        {
            drawMenuText(ctx, menu[i], positions[i][0], positions[i][1]);
        }
    }

    //Draw text for a menu option.
    function drawMenuText(ctx, option, xPos, yPos)
    {
        //Asterisk.
        ctx.fillText(
            "*",
            xPos + 2 * Math.floor(Math.random() * 1.0004),
            yPos + 2 * Math.floor(Math.random() * 1.0004));

        //Text offset.
        xPos += 32;

        //Draw characters.
        for(var i = 0; i < text.length; i++)
        {
            ctx.fillText(
                option.charAt(i),
                xPos + 2 * Math.floor(Math.random() * 1.0004),     //Random text wobble.
                yPos + 2 * Math.floor(Math.random() * 1.0004));
            xPos += ctx.measureText(option.charAt(i)).width;
        }
    }

    //Skip text growing entirely.
    function skip ()
    {
        charCounter = text.length;
    }

    //Reset text
    function reset()
    {
        charCounter = -1;
        timeCounter = timeAsterisk;
    }

    //Get the soul position for the option at a given menu index and style
    function getSoulPos (index, style)
    {
        var pos;

        switch(style)
        {
            case 0:
                pos = new Vect(
                    horizontalPositions[index][0] - 36,
                    horizontalPositions[index][1] - 18,
                    0);
                break;
            case 1:
                pos = new Vect(
                    verticalPositions[index][0] - 36,
                    verticalPositions[index][1] - 18,
                    0);
                break;
        }
        return pos;
    }

    return{
        init : init,
        setTimes : setTimes,
        setText : setText,
        update : update,
        drawText : drawText,
        drawMenu : drawMenu,
        skip : skip,
        reset : reset,
        getSoulPos : getSoulPos}
}());<commit_msg>Fixed Chrome/Opera audio corruption bug.<commit_after>//Dialogue writer and selector module for combat sequence.
var Cwriter = (function()
{
    var timeCheck = 0;         //Current interval to wait to place a character. Changes based on special characters.
    var timeAsterisk = .75;    //Interval to use for asterisk.
    var timePeriod = .33;      //Interval to use for periods.
    var timeComma = .21;       //Interval to use for commas.
    var timeStandard = .033;   //Interval to use for all other characters.

    var text;                  //Text to display.
    var charCounter;           //Counter for characters in text being displayed.
    var timeCounter;           //Tracks time for character counting.

    var horizontalPositions;   //Positions for horizontal menu.

    var verticalPositions;     //Positions for vertical menu.

    function init()
    {
        horizontalPositions =
        [
            [100, 296],
            [356, 296],
            [100, 328],
            [356, 328],
            [100, 360],
            [356, 360]
        ]

        verticalPositions =
        [
            [100, 296],
            [100, 328],
            [100, 360]
        ]
    }

    //Set the time delays of the writer.
    function setTimes(
        _timeAsterisk,
        _timePeriod,
        _timeComma,
        _timeStandard)
    {
        timeCheck = 0;
        timeAsterisk = _timeAsterisk;
        timePeriod = _timePeriod;
        timeComma = _timeComma;
        timeStandard = _timeStandard;
    }

    //Set the text for the writer and reset counters.
    function setText(_text)
    {
        text = _text;
        charCounter = -1;           //Counter for the index of the most recent displayed character.
        timeCounter = timeAsterisk; //Counter for the time since a character was placed.
    }

    //Update the writer.
    function update(dt)
    {
        if(myKeys.keydown[myKeys.KEYBOARD.KEY_X])
        {
            skip();
        }

        //Tick.
        timeCounter += dt;

        //If time to place a new character and if there is a new character.
        if(timeCounter > timeCheck && charCounter < text.length)
        {
            //Reset counter and increment current character for next character.
            timeCounter = timeCounter - timeCheck;
            charCounter++;

            //SFX

            //Change interval for new character.
            switch(text.charAt(charCounter))
            {
                case ".":
                    Sound.pauseSound("text");
                    timeCheck = timePeriod;
                    break;
                case ",":
                    Sound.pauseSound("text");
                    timeCheck = timeComma;
                    break;
                case "*":
                    timeCheck = timeAsterisk;
                    break;
                default:
                    Sound.playSound("text", false);
                    timeCheck = timeStandard;
                    break;
            }
        }

        if(charCounter >= text.length)
        {
            Sound.pauseSound("text");
        }
    }

    //Draw text.
    function drawText(ctx)
    {
        ctx.save();

        //Style.
        ctx.font = "24pt undertale";
        ctx.fillStyle = "#FFF";

        //Initial position.
        var textXPos = 52;
        var textYPos = 296;

        //Draw each active character, characters up to the character after the current character.
        for(var i = 0; i < charCounter + 1; i++)
        {
            //Display character if not last character and asterisk.
            if(
                text.charAt(i) != "*" ||
                text.charAt(i) != "|" ||
                i < charCounter)
            {
                ctx.fillText(
                    text.charAt(i),
                    textXPos + 2 * Math.floor(Math.random() * 1.0004),     //Random text wobble.
                    textYPos + 2 * Math.floor(Math.random() * 1.0004));
            }

            if(text.charAt(i + 1) == "|")
            {
                textXPos += ctx.measureText(text.charAt(i)).width;
                ctx.fillStyle = text.substring(i + 2, i + 6);
                i += 5;
            }
            else if(text.charAt(i + 1) == "\n") //New line moveover.
            {
                textXPos = 70;
                textYPos += 32;
            }
            else if(text.charAt(i + 1) == "*")  //Asterisk moveover
            {
                textXPos = 52;
                textYPos += 32;
            }
            else                                //Next-char moveover.
            {
                textXPos += ctx.measureText(text.charAt(i)).width;
            }
        }

        ctx.restore();
    }

    //Draw a menu.
    function drawMenu(ctx, menu, menuState, MENU_STATE)
    {
        ctx.save();

        //Style.
        ctx.font = "24pt undertale";
        ctx.fillStyle = "#FFF";

        switch(menuState)
        {
            case MENU_STATE.ACT:
                drawMenuTexts(ctx, menu, horizontalPositions);
                break;
            case MENU_STATE.ITEM:
                drawMenuTexts(ctx, menu, horizontalPositions);
                break;
            case MENU_STATE.MERCY:
                drawMenuTexts(ctx, menu, verticalPositions);
                break;
            default:
                drawMenuTexts(ctx, menu, verticalPositions);
                break;
        }

        ctx.restore();
    }

    //Draw text for all menu options.
    function drawMenuTexts(ctx, menu, positions)
    {
        for(var i = 0; i < menu.length; i++)
        {
            drawMenuText(ctx, menu[i], positions[i][0], positions[i][1]);
        }
    }

    //Draw text for a menu option.
    function drawMenuText(ctx, option, xPos, yPos)
    {
        //Asterisk.
        ctx.fillText(
            "*",
            xPos + 2 * Math.floor(Math.random() * 1.0004),
            yPos + 2 * Math.floor(Math.random() * 1.0004));

        //Text offset.
        xPos += 32;

        //Draw characters.
        for(var i = 0; i < text.length; i++)
        {
            ctx.fillText(
                option.charAt(i),
                xPos + 2 * Math.floor(Math.random() * 1.0004),     //Random text wobble.
                yPos + 2 * Math.floor(Math.random() * 1.0004));
            xPos += ctx.measureText(option.charAt(i)).width;
        }
    }

    //Skip text growing entirely.
    function skip ()
    {
        charCounter = text.length;
    }

    //Reset text
    function reset()
    {
        charCounter = -1;
        timeCounter = timeAsterisk;
    }

    //Get the soul position for the option at a given menu index and style
    function getSoulPos (index, style)
    {
        var pos;

        switch(style)
        {
            case 0:
                pos = new Vect(
                    horizontalPositions[index][0] - 36,
                    horizontalPositions[index][1] - 18,
                    0);
                break;
            case 1:
                pos = new Vect(
                    verticalPositions[index][0] - 36,
                    verticalPositions[index][1] - 18,
                    0);
                break;
        }
        return pos;
    }

    return{
        init : init,
        setTimes : setTimes,
        setText : setText,
        update : update,
        drawText : drawText,
        drawMenu : drawMenu,
        skip : skip,
        reset : reset,
        getSoulPos : getSoulPos}
}());<|endoftext|>


<commit_before>// Copyright 2012 Google Inc.  All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distrib-
// uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied.  See the License for
// specific language governing permissions and limitations under the License.

/**
 * @fileoverview An image map type that retries on error.
 * TODO(arb): find a name that doesn't suck...
 */
goog.provide('cm.ProxyTileMapType');
goog.require('cm.events');
goog.require('cm.ui');
goog.require('goog.style');

// How many retries of a tile fetch.
var MAX_RETRIES = 10;

var TRANSPARENT_TILE_REGEXP = /maps\.gstatic\.com\/mapfiles\/transparent\.png/;

/**
 * @class This class implements the MapType interface and
 * is provided for rendering image tiles. Unlike the Maps API ImageMapType,
 * this maptype retries images on error. The WMS/ESRI tile proxying code
 * signals that a tile isn't ready yet with a 417.
 *
 * @param {Object} opts Options for the layer.
 * @constructor
 * @extends google.maps.MVCObject
 */
cm.ProxyTileMapType = function(opts) {
  google.maps.MVCObject.call(this);
  this.getTileUrl = /** @type function(google.maps.Point, number):string */(
      opts['getTileUrl']);

  /**
   * A map of tile id: tile div, where 'id' is 'z,x,y'
   * @type Object.<Element>
   * @private
   */
  this.tiles_ = {};

  cm.events.onChange(this, 'opacity', this.updateOpacity_, this);

  /**
   * Maximum zoom of tiles for this maptype.
   * @type number
   * @private
   */
  this.maxZoom_ = opts['maxZoom'] || 19;
  /**
   * Minimum zoom of tiles for this maptype.
   * @type number
   * @private
   */
  this.minZoom_ = opts['minZoom'] || 0;
  /**
   * The tile size of this maptype. (Part of the MapType interface)
   * @type google.maps.Size
   */
  this.tileSize = opts['tileSize'] || new google.maps.Size(256, 256);

};
goog.inherits(cm.ProxyTileMapType, google.maps.MVCObject);

/**
 * Fetch a tile with the given coordinates. We create a div then set up
 * handlers to refresh the tile until it is successfully loaded.
 *
 * @param {google.maps.Point} coord The tile coordinates.
 * @param {number} zoom The zoom level.
 * @param {Document} ownerDocument The document.
 *
 * @return {Element} The freshly painted new div.
 */
cm.ProxyTileMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  // Create an empty tile div to paint later.
  var tileDiv = cm.ui.create('div');
  // Set tile width and height before painting it.
  tileDiv.style.width = this.tileSize.width + 'px';
  tileDiv.style.height = this.tileSize.height + 'px';

  var tileSrcUrl = this.getTileUrl(coord, zoom);
  if (!tileSrcUrl) {
    return tileDiv;
  }
  var tileCoords = zoom + ',' + coord.x + ',' + coord.y;
  this.tiles_[tileCoords] = tileDiv;

  var tileImg = cm.ui.create('img');
  goog.style.setOpacity(
      tileDiv, /** @type number */(this.get('opacity')));
  tileDiv.appendChild(tileImg);

  tileDiv.tileData = {
    tileSrc: tileSrcUrl,
    tileCoords: tileCoords,
    retries: 0,
    retryTimeout: null,
    startTime: new Date().getTime()
  };

  // TODO(arb): Create an "outstanding tiles" counter, and trigger the loading
  // spinner.

  // Now set up the event handlers.
  cm.events.listen(tileImg, 'load', function(e) {
    // Race condition here - we could be invoked after the tile has been
    // cleaned up. When the tile is painted, getTile() will be called before
    // a 'load' or 'error' event is fired, so we always expect the tile div's
    // data to be valid unless the tile has already been released.
    var tileData = tileDiv.tileData;
    if (!tileData) return;
    // Only log a succesful fetch if the loaded image is not a transparent tile.
    if (!TRANSPARENT_TILE_REGEXP.test(tileImg.src)) {
      cm.Analytics.logTime('wms_tile_fetch', tileData.retries,
                           new Date().getTime() - tileData.startTime,
                           tileData.tileSrc + ':' + tileData.tileCoords);
    }
    // TODO(arb): decrement the outstanding tile counter.
    tileData.retryTimeout = null;
  }, this);
  // Set up an error handler
  cm.events.listen(tileImg, 'error', function(e) {
    var tileData = tileDiv.tileData;
    // Race condition here, too.
    if (!tileData) return;
    var retries = tileData.retries;
    if (retries >= MAX_RETRIES) {
      cm.Analytics.logEvent(
          'wms_tile_fetch', 'failure', tileData.tileSrcUrl, 1);
      // Set back to an empty tile to avoid the nasty broken image icon.
      tileDiv.firstChild.setAttribute(
          'src', '//maps.gstatic.com/mapfiles/transparent.png');
      return;
    }
    tileData.retries = retries + 1;
    // Set back to an empty tile to avoid the nasty broken image icon.
    tileDiv.firstChild.setAttribute(
        'src', '//maps.gstatic.com/mapfiles/transparent.png');
    // TODO(arb): work out a reasonable retry approach.
    var retryDelay = Math.random() * 1000 * Math.pow(1.5, 2 + retries);
    tileData.retryTimeout = goog.global.setTimeout(function() {
      // You are in a twisty little maze of race conditions, all alike.
      if (!tileData) return;
      // Try to fetch the tile again.
      tileImg.removeAttribute('src');
      tileImg.setAttribute('src', tileData.tileSrc);
    }, retryDelay);
  }, this);

  // Finally, paint the tile.
  // TODO(arb): increment the outstanding tile counter.
  tileImg.setAttribute('src', tileSrcUrl);
  return tileDiv;
};

/**
 * This tile is no longer needed.
 * @param {Element} tileDiv The no-longer needed tile.
 */
cm.ProxyTileMapType.prototype.releaseTile = function(tileDiv) {
  if (tileDiv.tileData) {
    // Only bother with cleanup if we painted the tile.
    if (tileDiv.tileData.retryTimeout) {
      goog.global.clearTimeout(tileDiv.tileData.retryTimeout);
    }
    delete this.tiles_[tileDiv.tileData.tileCoords];
    tileDiv.tileData = null;
    while (tileDiv.firstChild) {
      cm.events.dispose(tileDiv.firstChild);
      tileDiv.removeChild(tileDiv.firstChild);
    }
  }
};

/**
 * Event handler invoked when the 'opacity' attribute is changed.
 * @private
 */
cm.ProxyTileMapType.prototype.updateOpacity_ = function() {
  var opacity = /** @type number */(this.get('opacity'));
  for (var tileCoords in this.tiles_) {
    var tile = /** @type {!Element} */(this.tiles_[tileCoords]);
    goog.style.setOpacity(tile, opacity);
  }
};

// For some reason saying 'implements google.maps.MapType' in the class
// makes jscompiler choke on the constructor. This is b/7395824
goog.exportProperty(cm.ProxyTileMapType.prototype, 'getTile',
                    cm.ProxyTileMapType.prototype.getTile);
goog.exportProperty(cm.ProxyTileMapType.prototype, 'releaseTile',
                    cm.ProxyTileMapType.prototype.releaseTile);
<commit_msg>Don't log analytics events when tile fetch retries exceed maximum since the per-session analytics hit limit is met too easily. Also pass in a string for the number of retries for the timing log. ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=46050214<commit_after>// Copyright 2012 Google Inc.  All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distrib-
// uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied.  See the License for
// specific language governing permissions and limitations under the License.

/**
 * @fileoverview An image map type that retries on error.
 * TODO(arb): find a name that doesn't suck...
 */
goog.provide('cm.ProxyTileMapType');
goog.require('cm.events');
goog.require('cm.ui');
goog.require('goog.style');

// How many retries of a tile fetch.
var MAX_RETRIES = 10;

var TRANSPARENT_TILE_REGEXP = /maps\.gstatic\.com\/mapfiles\/transparent\.png/;

/**
 * @class This class implements the MapType interface and
 * is provided for rendering image tiles. Unlike the Maps API ImageMapType,
 * this maptype retries images on error. The WMS/ESRI tile proxying code
 * signals that a tile isn't ready yet with a 417.
 *
 * @param {Object} opts Options for the layer.
 * @constructor
 * @extends google.maps.MVCObject
 */
cm.ProxyTileMapType = function(opts) {
  google.maps.MVCObject.call(this);
  this.getTileUrl = /** @type function(google.maps.Point, number):string */(
      opts['getTileUrl']);

  /**
   * A map of tile id: tile div, where 'id' is 'z,x,y'
   * @type Object.<Element>
   * @private
   */
  this.tiles_ = {};

  cm.events.onChange(this, 'opacity', this.updateOpacity_, this);

  /**
   * Maximum zoom of tiles for this maptype.
   * @type number
   * @private
   */
  this.maxZoom_ = opts['maxZoom'] || 19;
  /**
   * Minimum zoom of tiles for this maptype.
   * @type number
   * @private
   */
  this.minZoom_ = opts['minZoom'] || 0;
  /**
   * The tile size of this maptype. (Part of the MapType interface)
   * @type google.maps.Size
   */
  this.tileSize = opts['tileSize'] || new google.maps.Size(256, 256);

};
goog.inherits(cm.ProxyTileMapType, google.maps.MVCObject);

/**
 * Fetch a tile with the given coordinates. We create a div then set up
 * handlers to refresh the tile until it is successfully loaded.
 *
 * @param {google.maps.Point} coord The tile coordinates.
 * @param {number} zoom The zoom level.
 * @param {Document} ownerDocument The document.
 *
 * @return {Element} The freshly painted new div.
 */
cm.ProxyTileMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  // Create an empty tile div to paint later.
  var tileDiv = cm.ui.create('div');
  // Set tile width and height before painting it.
  tileDiv.style.width = this.tileSize.width + 'px';
  tileDiv.style.height = this.tileSize.height + 'px';

  var tileSrcUrl = this.getTileUrl(coord, zoom);
  if (!tileSrcUrl) {
    return tileDiv;
  }
  var tileCoords = zoom + ',' + coord.x + ',' + coord.y;
  this.tiles_[tileCoords] = tileDiv;

  var tileImg = cm.ui.create('img');
  goog.style.setOpacity(
      tileDiv, /** @type number */(this.get('opacity')));
  tileDiv.appendChild(tileImg);

  tileDiv.tileData = {
    tileSrc: tileSrcUrl,
    tileCoords: tileCoords,
    retries: 0,
    retryTimeout: null,
    startTime: new Date().getTime()
  };

  // TODO(arb): Create an "outstanding tiles" counter, and trigger the loading
  // spinner.

  // Now set up the event handlers.
  cm.events.listen(tileImg, 'load', function(e) {
    // Race condition here - we could be invoked after the tile has been
    // cleaned up. When the tile is painted, getTile() will be called before
    // a 'load' or 'error' event is fired, so we always expect the tile div's
    // data to be valid unless the tile has already been released.
    var tileData = tileDiv.tileData;
    if (!tileData) return;
    // Only log a succesful fetch if the loaded image is not a transparent tile.
    if (!TRANSPARENT_TILE_REGEXP.test(tileImg.src)) {
      cm.Analytics.logTime('wms_tile_fetch', tileData.retries + '',
                           new Date().getTime() - tileData.startTime,
                           tileData.tileSrc + ':' + tileData.tileCoords);
    }
    // TODO(arb): decrement the outstanding tile counter.
    tileData.retryTimeout = null;
  }, this);
  // Set up an error handler
  cm.events.listen(tileImg, 'error', function(e) {
    var tileData = tileDiv.tileData;
    // Race condition here, too.
    if (!tileData) return;
    var retries = tileData.retries;
    if (retries >= MAX_RETRIES) {
      // Set back to an empty tile to avoid the nasty broken image icon.
      tileDiv.firstChild.setAttribute(
          'src', '//maps.gstatic.com/mapfiles/transparent.png');
      return;
    }
    tileData.retries = retries + 1;
    // Set back to an empty tile to avoid the nasty broken image icon.
    tileDiv.firstChild.setAttribute(
        'src', '//maps.gstatic.com/mapfiles/transparent.png');
    // TODO(arb): work out a reasonable retry approach.
    var retryDelay = Math.random() * 1000 * Math.pow(1.5, 2 + retries);
    tileData.retryTimeout = goog.global.setTimeout(function() {
      // You are in a twisty little maze of race conditions, all alike.
      if (!tileData) return;
      // Try to fetch the tile again.
      tileImg.removeAttribute('src');
      tileImg.setAttribute('src', tileData.tileSrc);
    }, retryDelay);
  }, this);

  // Finally, paint the tile.
  // TODO(arb): increment the outstanding tile counter.
  tileImg.setAttribute('src', tileSrcUrl);
  return tileDiv;
};

/**
 * This tile is no longer needed.
 * @param {Element} tileDiv The no-longer needed tile.
 */
cm.ProxyTileMapType.prototype.releaseTile = function(tileDiv) {
  if (tileDiv.tileData) {
    // Only bother with cleanup if we painted the tile.
    if (tileDiv.tileData.retryTimeout) {
      goog.global.clearTimeout(tileDiv.tileData.retryTimeout);
    }
    delete this.tiles_[tileDiv.tileData.tileCoords];
    tileDiv.tileData = null;
    while (tileDiv.firstChild) {
      cm.events.dispose(tileDiv.firstChild);
      tileDiv.removeChild(tileDiv.firstChild);
    }
  }
};

/**
 * Event handler invoked when the 'opacity' attribute is changed.
 * @private
 */
cm.ProxyTileMapType.prototype.updateOpacity_ = function() {
  var opacity = /** @type number */(this.get('opacity'));
  for (var tileCoords in this.tiles_) {
    var tile = /** @type {!Element} */(this.tiles_[tileCoords]);
    goog.style.setOpacity(tile, opacity);
  }
};

// For some reason saying 'implements google.maps.MapType' in the class
// makes jscompiler choke on the constructor. This is b/7395824
goog.exportProperty(cm.ProxyTileMapType.prototype, 'getTile',
                    cm.ProxyTileMapType.prototype.getTile);
goog.exportProperty(cm.ProxyTileMapType.prototype, 'releaseTile',
                    cm.ProxyTileMapType.prototype.releaseTile);
<|endoftext|>


<commit_before>var TOC = require('../ui/toc');
var each = require('lodash/collection/each');

function DocumentationTOC() {
  TOC.apply(this, arguments);
}

DocumentationTOC.Prototype = function() {

  this.computeEntries = function() {
    var doc = this.getDocument();
    var config = this.getConfig();

    var entries = [];
    var contentNodes = doc.get('body').nodes;

    contentNodes.forEach(function(nsId) {
      var ns = doc.get(nsId);
      entries.push({
        id: nsId,
        name: ns.name,
        level: 1,
        node: ns
      });

      each(ns.getMemberCategories(), function(cat) {
        var catMembers = ns.getCategoryMembers(cat, config);
        catMembers.forEach(function(catMember) {
          entries.push({
            id: catMember.id,
            name: catMember.name,
            level: 2,
            node: catMember
          });
        });
      });
    }.bind(this));
    return entries;
  };
};

TOC.extend(DocumentationTOC);

DocumentationTOC.static.tocTypes = ['namespace', 'class', 'function', 'module'];

module.exports = DocumentationTOC;
<commit_msg>fixing module filename<commit_after>var TOC = require('../ui/TOC');
var each = require('lodash/collection/each');

function DocumentationTOC() {
  TOC.apply(this, arguments);
}

DocumentationTOC.Prototype = function() {

  this.computeEntries = function() {
    var doc = this.getDocument();
    var config = this.getConfig();

    var entries = [];
    var contentNodes = doc.get('body').nodes;

    contentNodes.forEach(function(nsId) {
      var ns = doc.get(nsId);
      entries.push({
        id: nsId,
        name: ns.name,
        level: 1,
        node: ns
      });

      each(ns.getMemberCategories(), function(cat) {
        var catMembers = ns.getCategoryMembers(cat, config);
        catMembers.forEach(function(catMember) {
          entries.push({
            id: catMember.id,
            name: catMember.name,
            level: 2,
            node: catMember
          });
        });
      });
    }.bind(this));
    return entries;
  };
};

TOC.extend(DocumentationTOC);

DocumentationTOC.static.tocTypes = ['namespace', 'class', 'function', 'module'];

module.exports = DocumentationTOC;
<|endoftext|>


<commit_before>module("Basic Tests");

test("conversions", function() {
    equal(milesToKilometers(10), "16 kilometers");
    equal(convertImperialToSI("fahrenheit", "-40"), "-40 Celsius");
    equal(convertImperialToSI("fahrenheit", "33.8"), "1 Celsius");
});

test("singularization", function() {
    var str = "mile miles foot feet fahrenheit fahrenheits yard yards "
        + "gallon gallons ounce ounces pound pounds inch inches";
    var exp = "mile mile foot foot fahrenheit fahrenheit yard yard "
        + "gallon gallon ounce ounce pound pound inch inch";
    equal(singularizeUnits(str), exp);
});

module("Search with regexps");

test("multiple occurrence search", function() {
    var cases = [
        {
            text: "foo 1 mile 2 miles 3 miles baz",
            expected: [
                {
                    index: 4,
                    match: "1 mile",
                    numeral: 1,
                    units: "mile"
                },
                {
                    index: 11,
                    match: "2 miles",
                    numeral: 2,
                    units: "mile"
                },
                {
                    index: 19,
                    match: "3 miles",
                    numeral: 3,
                    units: "mile"
                }
            ]
        },
        {
            text: "fly 3,600 miles and walk 3 miles",
            expected: [
                {
                    index: 4,
                    match: "3,600 miles",
                    numeral: 3600,
                    units: "mile"
                },
                {
                    index: 25,
                    match: "3 miles",
                    numeral: 3,
                    units: "mile"
                }
            ]
        },
        {
            text: "fly 100 yards and walk 1000 feet 40 Fahrenheit",
            expected: [
                {
                    index: 4,
                    match: "100 yards",
                    numeral: 100,
                    units: "yard"
                },
                {
                    index: 23,
                    match: "1000 feet",
                    numeral: 1000,
                    units: "foot"
                },
                {
                    index: 33,
                    match: "40 Fahrenheit",
                    numeral: 40,
                    units: "fahrenheit"
                }
            ]
        },
        {
            text: "foo bar baz",
            expected: []
        },
        {
            text: "60-inch telescope, 12 inches, 1 inch",
            expected: [
                {
                    index: 0,
                    match: "60-inch",
                    numeral: 60,
                    units: "inch"
                },
                {
                    index: 19,
                    match: "12 inches",
                    numeral: 12,
                    units: "inch"
                },
                {
                    index: 30,
                    match: "1 inch",
                    numeral: 1,
                    units: "inch"
                }
            ]
        },
        {
            text: "The 1.35 mile self-guided nature trail",
            expected: [
                {
                    index: 4,
                    match: "1.35 mile",
                    numeral: 1.35,
                    units: "mile"
                }
            ]
        },
        {
            text: "The Black Bear Trail is 0.6 miles long",
            expected: [
                {
                    index: 24,
                    match: "0.6 miles",
                    numeral: 0.6,
                    units: "mile"
                }
            ]
        },
        {
            // A bug used to match this, treating "." as a malformed number and
            // "In" as inches. Adding this negative test here to guard against
            // regressions.
            text: "follow. Instead",
            expected: []
        }
    ]
    cases.forEach(function(testCase) {
        results = multisearch(testCase.text)
        equal(results.length, testCase.expected.length,
            "results length must match for test '" + testCase.text + "'");
        for (var i = 0; i < results.length; ++i) {
            deepEqual(results[i], testCase.expected[i],
                testCase.text + ". " + i + "th search");
        }
    });
});
<commit_msg>Add tests for all conversions<commit_after>module("Basic Tests");

test("conversions", function() {
    equal(milesToKilometers(10), "16 kilometers");
    equal(convertImperialToSI("fahrenheit", "-40"), "-40 Celsius");
    equal(convertImperialToSI("fahrenheit", "33.8"), "1 Celsius");

    equal(convertImperialToSI("mile", "10"), "16 kilometers");
    equal(convertImperialToSI("foot", "10"), "3 meters");
    equal(convertImperialToSI("yard", "10"), "9 meters");
    equal(convertImperialToSI("gallon", "10"), "37.8541 liters");
    equal(convertImperialToSI("ounce", "10"), "283.495 grams");
    equal(convertImperialToSI("oz", "10"), "283.495 grams");
    equal(convertImperialToSI("pound", "10"), "4.53592 kilograms");
    equal(convertImperialToSI("inch", "10"), "25.4 centimeters");
    equal(convertImperialToSI("in", "10"), "25.4 centimeters");

    equal(convertImperialToSI("disexisting-unit", "10"), "10 disexisting-unit");
});

test("singularization", function() {
    var str = "mile miles foot feet fahrenheit fahrenheits yard yards "
        + "gallon gallons ounce ounces pound pounds inch inches";
    var exp = "mile mile foot foot fahrenheit fahrenheit yard yard "
        + "gallon gallon ounce ounce pound pound inch inch";
    equal(singularizeUnits(str), exp);
});

module("Search with regexps");

test("multiple occurrence search", function() {
    var cases = [
        {
            text: "foo 1 mile 2 miles 3 miles baz",
            expected: [
                {
                    index: 4,
                    match: "1 mile",
                    numeral: 1,
                    units: "mile"
                },
                {
                    index: 11,
                    match: "2 miles",
                    numeral: 2,
                    units: "mile"
                },
                {
                    index: 19,
                    match: "3 miles",
                    numeral: 3,
                    units: "mile"
                }
            ]
        },
        {
            text: "fly 3,600 miles and walk 3 miles",
            expected: [
                {
                    index: 4,
                    match: "3,600 miles",
                    numeral: 3600,
                    units: "mile"
                },
                {
                    index: 25,
                    match: "3 miles",
                    numeral: 3,
                    units: "mile"
                }
            ]
        },
        {
            text: "fly 100 yards and walk 1000 feet 40 Fahrenheit",
            expected: [
                {
                    index: 4,
                    match: "100 yards",
                    numeral: 100,
                    units: "yard"
                },
                {
                    index: 23,
                    match: "1000 feet",
                    numeral: 1000,
                    units: "foot"
                },
                {
                    index: 33,
                    match: "40 Fahrenheit",
                    numeral: 40,
                    units: "fahrenheit"
                }
            ]
        },
        {
            text: "foo bar baz",
            expected: []
        },
        {
            text: "60-inch telescope, 12 inches, 1 inch",
            expected: [
                {
                    index: 0,
                    match: "60-inch",
                    numeral: 60,
                    units: "inch"
                },
                {
                    index: 19,
                    match: "12 inches",
                    numeral: 12,
                    units: "inch"
                },
                {
                    index: 30,
                    match: "1 inch",
                    numeral: 1,
                    units: "inch"
                }
            ]
        },
        {
            text: "The 1.35 mile self-guided nature trail",
            expected: [
                {
                    index: 4,
                    match: "1.35 mile",
                    numeral: 1.35,
                    units: "mile"
                }
            ]
        },
        {
            text: "The Black Bear Trail is 0.6 miles long",
            expected: [
                {
                    index: 24,
                    match: "0.6 miles",
                    numeral: 0.6,
                    units: "mile"
                }
            ]
        },
        {
            // A bug used to match this, treating "." as a malformed number and
            // "In" as inches. Adding this negative test here to guard against
            // regressions.
            text: "follow. Instead",
            expected: []
        }
    ]
    cases.forEach(function(testCase) {
        results = multisearch(testCase.text)
        equal(results.length, testCase.expected.length,
            "results length must match for test '" + testCase.text + "'");
        for (var i = 0; i < results.length; ++i) {
            deepEqual(results[i], testCase.expected[i],
                testCase.text + ". " + i + "th search");
        }
    });
});
<|endoftext|>


<commit_before>var aggregate_nodes = function(prop1,prop2){
    modes.generation+=1
    var aggregates = {}
    for (var node in graph.nodes){
      node = graph.nodes[node]
      var p1 = node[prop1]
      var p2 = node[prop2]
      if(!aggregates[p1+","+p2]){
        aggregates[p1+","+p2] = []
      }
      aggregates[p1+","+p2].push(node)
      // console.log(p1,p2)
    }
    // console.log(aggregates)
    var aggregates_list = []
    for(var key in aggregates){
      aggregates_list.push(aggregates[key])
    }
    var agg_nodes = []
    var i = 0
    for (var agg in aggregates_list){
      agg = aggregates_list[agg]
      agg_node = {}
      agg_node.id = "agg"+modes.generation+"i"+i
      i++
      agg_node.x_list = {}
      agg_node.y_list = {}
      agg_node.r_list = {}
      agg_node.nodes = agg
      agg_node.count = agg.length
      agg_node.degree = agg[0].degree
      agg_node.modularity_class = agg[0].modularity_class
      agg_node.gender = agg[0].gender
      //currently only can size by count
      //we'll need some non-graph-based properties
      agg_node.x_list[modes.generation] = xscale(agg_node[prop1])
      agg_node.y_list[modes.generation] = yscale(agg_node[prop2])
      agg_node.r_list[modes.generation] = agg_node.count*5
      agg_nodes.push(agg_node)
    }
    // console.log(agg_nodes)
    node_generations[modes.generation] = agg_glyphs = nodeg.selectAll(".node[generation='"+modes.generation+"']")
      .data(agg_nodes, function(d){return d.id})
    .enter().append("circle")
      .classed("node",true)
      .classed("aggregate",true)
      .attr("generation",modes.generation)
      .attr("nodeid", function(d){return d.id})
      .attr("r",0)
      .attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      .on("mouseover",function(d){
        d3.select(this).attr("fill",function(d){ return color(d.modularity_class); })
      })
      .on("mouseout",function(d){
        d3.select(this).attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      })

  agg_glyphs.append("title")
      .text(function(d){ return d.label; })

  node_generations[modes.active_generation]
    // .each(function(d){
    //   d.r_list[modes.active_generation] = 0
    // })
    .transition().duration(transition_duration)
      .attr("r",0)

  agg_generations[modes.generation] = {}
  agg_generations[modes.generation].source_gen = modes.active_generation
  modes.active_generation = modes.generation
  node = agg_glyphs

  node
    .attr("cx", function(d) { return d.x_list[modes.active_generation]; })
    .attr("cy", function(d) { return d.y_list[modes.active_generation]; });

  node.transition().duration(transition_duration)
    .attr("r",function(d){
      return d.r_list[modes.generation]
    })

}

var deaggregate_nodes = function(agg_gen){
  try{
    if(node_generations[agg_gen].data()[0].id.indexOf("agg")!=0){
      console.log("nope, not aggregate")
      return
    }else{
      console.log("yep, aggregate")
      modes.active_generation = agg_generations[agg_gen]
      node_generations[agg_gen]
        .transition().duration(transition_duration)
          .attr("r",0)
        .remove()

      node_generations[modes.active_generation]
        .transition().duration(transition_duration)
          .attr("r",function(d){return d.r_list[modes.active_generation]})

      node_generations[agg_gen] = null
      agg_generations[agg_gen] = null

    }
  }catch(err){
    console.log("nope, not aggregate")
  }
}

var deaggregate_0 = function(){
  deaggregate_nodes(0)
}

var deaggregate_1 = function(){
  deaggregate_nodes(1)
}

var aggregate_nodes_by_gender_and_category = function(){
  aggregate_nodes("gender","modularity_class")
}

var clone_active_set = function(){
  //Stamps a copy of the current position
  //of the nodes.
  modes.generation+=1
  node_generations[modes.generation] = nodeclone = nodeg.selectAll(".node[generation='"+modes.generation+"']")
      .data(graph.nodes, function(d){return d.id})
    .enter().append("circle")
      .classed("node",true)
      .attr("generation",modes.generation)
      .attr("nodeid", function(d){return d.id})
      .attr("r",function(d){
          d.r_list[modes.generation] = d.r_list[modes.active_generation]
          return d.r_list[modes.generation]
        })
      .attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      .on("mouseover",function(d){
        d3.select(this).attr("fill",function(d){ return color(d.modularity_class); })
      })
      .on("mouseout",function(d){
        d3.select(this).attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      })

  nodeclone.append("title")
      .text(function(d){ return d.label; })

  nodeclone
    .each(function(d){ d.x_list[modes.generation] = d.x_list[modes.active_generation]})
    .each(function(d){ d.y_list[modes.generation] = d.y_list[modes.active_generation]})

  modes.active_generation = modes.generation
  node = nodeclone

  node
    .attr("cx", function(d) { return d.x_list[modes.active_generation]; })
    .attr("cy", function(d) { return d.y_list[modes.active_generation]; });

}

var remove_generation = function(gen){
  if(gen==0){ return; } //cannot remove primary nodes
  if(gen==modes.active_generation){
    select_generation(0) //select primary nodes
    to_remove = node_generations[gen]
    node_generations[gen] = null
    to_remove.remove()
  }
  if(gen==modes.source_generation){
    modes.source_generation = 0
  }
  if(gen==modes.target_generation){
    modes.target_generation = 0
  }
  update_links()
}

var remove_generation_1 = function(){
  remove_generation(1)
}

//Select Generations
var select_generation = function(gen){
  modes.active_generation = gen
  node = node_generations[modes.active_generation]
}

var select_generation_0 = function(){
  select_generation(0)
}

var select_generation_1 = function(){
  select_generation(1)
}

var select_generation_2 = function(){
  select_generation(2)
}

var evenly_position_on_x = function(){
  xscale = d3.scale.ordinal()
    .domain(graph.nodes.map(function(d){ return d.id; }))
    .rangePoints([0,width])

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

var evenly_position_on_y = function(){
  yscale = d3.scale.ordinal()
    .domain(graph.nodes.map(function(d){ return d.id; }))
    .rangePoints([0,height])

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_y_top = function(){
  yscale = function(d){
    return 0-0.5*ybuffer;
  }

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_y_middle = function(){
  yscale = function(d){
    return height/2;
  }

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_y_bottom = function(){
  yscale = function(d){
    return height+0.5*ybuffer;
  }

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_x_left = function(){
  xscale = function(d){
    return 0-0.5*xbuffer;
  }

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

var position_x_center = function(){
  xscale = function(d){
    return width/2;
  }

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

var position_x_right = function(){
  xscale = function(d){
    return width+0.5*xbuffer;
  }

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

<commit_msg>deaggregation working<commit_after>var aggregate_nodes = function(prop1,prop2){
    modes.generation+=1
    var aggregates = {}
    for (var node in graph.nodes){
      node = graph.nodes[node]
      var p1 = node[prop1]
      var p2 = node[prop2]
      if(!aggregates[p1+","+p2]){
        aggregates[p1+","+p2] = []
      }
      aggregates[p1+","+p2].push(node)
      // console.log(p1,p2)
    }
    // console.log(aggregates)
    var aggregates_list = []
    for(var key in aggregates){
      aggregates_list.push(aggregates[key])
    }
    var agg_nodes = []
    var i = 0
    for (var agg in aggregates_list){
      agg = aggregates_list[agg]
      agg_node = {}
      agg_node.id = "agg"+modes.generation+"i"+i
      i++
      agg_node.x_list = {}
      agg_node.y_list = {}
      agg_node.r_list = {}
      agg_node.nodes = agg
      agg_node.count = agg.length
      agg_node.degree = agg[0].degree
      agg_node.modularity_class = agg[0].modularity_class
      agg_node.gender = agg[0].gender
      //currently only can size by count
      //we'll need some non-graph-based properties
      agg_node.x_list[modes.generation] = xscale(agg_node[prop1])
      agg_node.y_list[modes.generation] = yscale(agg_node[prop2])
      agg_node.r_list[modes.generation] = agg_node.count*5
      agg_nodes.push(agg_node)
    }
    // console.log(agg_nodes)
    node_generations[modes.generation] = agg_glyphs = nodeg.selectAll(".node[generation='"+modes.generation+"']")
      .data(agg_nodes, function(d){return d.id})
    .enter().append("circle")
      .classed("node",true)
      .classed("aggregate",true)
      .attr("generation",modes.generation)
      .attr("nodeid", function(d){return d.id})
      .attr("r",0)
      .attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      .on("mouseover",function(d){
        d3.select(this).attr("fill",function(d){ return color(d.modularity_class); })
      })
      .on("mouseout",function(d){
        d3.select(this).attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      })

  agg_glyphs.append("title")
      .text(function(d){ return d.label; })

  node_generations[modes.active_generation]
    // .each(function(d){
    //   d.r_list[modes.active_generation] = 0
    // })
    .transition().duration(transition_duration)
      .attr("r",0)

  agg_generations[modes.generation] = {}
  agg_generations[modes.generation].source_gen = modes.active_generation
  modes.active_generation = modes.generation
  node = agg_glyphs

  node
    .attr("cx", function(d) { return d.x_list[modes.active_generation]; })
    .attr("cy", function(d) { return d.y_list[modes.active_generation]; });

  node.transition().duration(transition_duration)
    .attr("r",function(d){
      return d.r_list[modes.generation]
    })

}

var deaggregate_nodes = function(agg_gen){
  try{
    if(node_generations[agg_gen].data()[0].id.indexOf("agg")!=0){
      // console.log("nope, not aggregate")
      return
    }else{
      // console.log("yep, aggregate")
      modes.active_generation = agg_generations[agg_gen].source_gen
      node_generations[agg_gen]
        .transition().duration(transition_duration)
          .attr("r",0)
        .remove()

      node_generations[modes.active_generation]
        .transition().duration(transition_duration)
          .attr("r",function(d){return d.r_list[modes.active_generation]})

      node_generations[agg_gen] = null
      agg_generations[agg_gen] = null

    }
  }catch(err){
    // console.log("nope, not aggregate")
  }
}

var deaggregate_0 = function(){
  deaggregate_nodes(0)
}

var deaggregate_1 = function(){
  deaggregate_nodes(1)
}

var aggregate_nodes_by_gender_and_category = function(){
  aggregate_nodes("gender","modularity_class")
}

var clone_active_set = function(){
  //Stamps a copy of the current position
  //of the nodes.
  modes.generation+=1
  node_generations[modes.generation] = nodeclone = nodeg.selectAll(".node[generation='"+modes.generation+"']")
      .data(graph.nodes, function(d){return d.id})
    .enter().append("circle")
      .classed("node",true)
      .attr("generation",modes.generation)
      .attr("nodeid", function(d){return d.id})
      .attr("r",function(d){
          d.r_list[modes.generation] = d.r_list[modes.active_generation]
          return d.r_list[modes.generation]
        })
      .attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      .on("mouseover",function(d){
        d3.select(this).attr("fill",function(d){ return color(d.modularity_class); })
      })
      .on("mouseout",function(d){
        d3.select(this).attr("fill", function(d){ return d3.rgb(color(d.modularity_class)).darker(); })
      })

  nodeclone.append("title")
      .text(function(d){ return d.label; })

  nodeclone
    .each(function(d){ d.x_list[modes.generation] = d.x_list[modes.active_generation]})
    .each(function(d){ d.y_list[modes.generation] = d.y_list[modes.active_generation]})

  modes.active_generation = modes.generation
  node = nodeclone

  node
    .attr("cx", function(d) { return d.x_list[modes.active_generation]; })
    .attr("cy", function(d) { return d.y_list[modes.active_generation]; });

}

var remove_generation = function(gen){
  if(gen==0){ return; } //cannot remove primary nodes
  if(gen==modes.active_generation){
    select_generation(0) //select primary nodes
    to_remove = node_generations[gen]
    node_generations[gen] = null
    to_remove.remove()
  }
  if(gen==modes.source_generation){
    modes.source_generation = 0
  }
  if(gen==modes.target_generation){
    modes.target_generation = 0
  }
  update_links()
}

var remove_generation_1 = function(){
  remove_generation(1)
}

//Select Generations
var select_generation = function(gen){
  modes.active_generation = gen
  node = node_generations[modes.active_generation]
}

var select_generation_0 = function(){
  select_generation(0)
}

var select_generation_1 = function(){
  select_generation(1)
}

var select_generation_2 = function(){
  select_generation(2)
}

var evenly_position_on_x = function(){
  xscale = d3.scale.ordinal()
    .domain(graph.nodes.map(function(d){ return d.id; }))
    .rangePoints([0,width])

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

var evenly_position_on_y = function(){
  yscale = d3.scale.ordinal()
    .domain(graph.nodes.map(function(d){ return d.id; }))
    .rangePoints([0,height])

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_y_top = function(){
  yscale = function(d){
    return 0-0.5*ybuffer;
  }

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_y_middle = function(){
  yscale = function(d){
    return height/2;
  }

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_y_bottom = function(){
  yscale = function(d){
    return height+0.5*ybuffer;
  }

  node.each(function(d){
    d.y_list[modes.active_generation] = yscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cy",function(d){ return d.y_list[modes.active_generation] })

  update_links()
}

var position_x_left = function(){
  xscale = function(d){
    return 0-0.5*xbuffer;
  }

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

var position_x_center = function(){
  xscale = function(d){
    return width/2;
  }

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

var position_x_right = function(){
  xscale = function(d){
    return width+0.5*xbuffer;
  }

  node.each(function(d){
    d.x_list[modes.active_generation] = xscale(d.id)
  })

  node.transition().duration(transition_duration)
    .attr("cx",function(d){ return d.x_list[modes.active_generation] })

  update_links()
}

<|endoftext|>


<commit_before>"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
    for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
        to[j] = from[i];
    return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = exports.uuidIdProvider = void 0;
var uuid_1 = require("uuid");
var types_1 = require("./types");
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
var uuidIdProvider = function () { return uuid_1.v4(); };
exports.uuidIdProvider = uuidIdProvider;
var create = function (getId) {
    var modules = [];
    var getDefinitionLookup = function () { return modules.reduce(function (definitionLookup, module) {
        return module.definitions.reduce(function (lookup, definition) {
            lookup[definition.fullName] = definition;
            return lookup;
        }, definitionLookup);
    }, {}); };
    var getDefinition = function (fullName) { return getDefinitionLookup()[fullName]; };
    var registerModule = function (module) {
        module.definitions.forEach(function (definition) {
            definition.icon = definition.icon || 'nodox:core_nodox';
            var existingDef = getDefinition(definition.fullName);
            if (existingDef) {
                throw new Error("duplicate definition (" + definition.fullName + "): " + module.name + " and " + existingDef.moduleName);
            }
        });
        var moduleNameSpaces = modules.map(function (m) { return m.namespace; });
        module.dependencies.forEach(function (dependency) {
            if (!moduleNameSpaces.includes(dependency)) {
                throw new Error("Module '" + module.namespace + "' dependency not met: " + dependency);
            }
        });
        modules.push(module);
    };
    var getModules = function () { return modules; };
    var byId = function (id) { return function (item) { return id === item.id; }; };
    var getNode = function (document, nodeId) { return document.nodes.find(byId(nodeId)); };
    var getConnection = function (document, connectionId) { return document.connections.find(byId(connectionId)); };
    var getInput = function (document, inputId) {
        var node = document.nodes.find(function (node) { return node.inputs.find(byId(inputId)) !== undefined; });
        return { node: node, connector: node === null || node === void 0 ? void 0 : node.inputs.find(byId(inputId)) };
    };
    var getOutput = function (document, outputId) {
        var node = document.nodes.find(function (node) { return node.inputs.find(byId(outputId)) !== undefined; });
        return { node: node, connector: node === null || node === void 0 ? void 0 : node.outputs.find(byId(outputId)) };
    };
    var getConnector = function (document, id) {
        var _a = getInput(document, id), node = _a.node, connector = _a.connector;
        return connector !== undefined ? { node: node, connector: connector } : getOutput(document, id);
    };
    var indexOfConnector = function (node, connector) {
        var index = node.inputs.findIndex(byId(connector.id));
        return index > -1 ? index : node.outputs.findIndex(byId(connector.id));
    };
    var getNodeFromConnector = function (document, connector) {
        var node = getNode(document, connector.nodeId);
        return node;
    };
    var removeConnection = function (document, connectionId) {
        var connection = getConnection(document, connectionId);
        if (connection !== undefined) {
            var input = getInput(document, connection.inputConnectorId).connector;
            if (input !== undefined) {
                delete input.connectionId;
            }
            var output = getOutput(document, connection.outputConnectorId).connector;
            if (output !== undefined) {
                delete output.connectionId;
            }
            var index = document.connections.indexOf(connection);
            if (index > -1) {
                document.connections.splice(index, 1);
            }
        }
    };
    var connect = function (document, firstConnector, secondConnector) {
        var _a = firstConnector.connectorType === types_1.ConnectorType.input
            ? { inputConnector: firstConnector, outputConnector: secondConnector }
            : { inputConnector: secondConnector, outputConnector: firstConnector }, inputConnector = _a.inputConnector, outputConnector = _a.outputConnector;
        if (outputConnector.connectionId !== types_1.ConnectorType.output || !canAcceptConnection(outputConnector, inputConnector)) {
            return undefined;
        }
        var currentInputConnections = document
            .connections
            .filter(function (connection) { return connection.inputConnectorId === inputConnector.id; })
            .map(function (connection) { return connection.id; });
        var connection = {
            id: getId(),
            inputConnectorId: inputConnector.id,
            outputConnectorId: outputConnector.id
        };
        inputConnector.connectionId = connection.id;
        currentInputConnections.forEach(function (id) {
            removeConnection(document, id);
        });
        document.connections.push(connection);
        return connection;
    };
    var createNewDocument = function (metaData) {
        var newDocument = {
            id: getId(),
            name: 'New Nodox document',
            connections: [],
            nodes: [],
            metaData: metaData
        };
        return newDocument;
    };
    /**
     * Assigns new ids to document, nodes, node inputs, node outputs and connections
     * used for cloning a document
     * @param document
     */
    var reAssignIds = function (document) {
        document.id = getId();
        document.name += '.cloned';
        var oldConnectorIds = {};
        document.nodes.forEach(function (n) {
            var newId = getId();
            oldConnectorIds[n.id] = newId;
            n.id = newId;
            n.inputs.forEach(function (inputConnector) {
                var newInputId = getId();
                inputConnector.nodeId = n.id;
                oldConnectorIds[inputConnector.id] = newInputId;
                inputConnector.id = newInputId;
            });
            n.outputs.forEach(function (outputConnector) {
                var newOutputId = getId();
                outputConnector.nodeId = n.id;
                oldConnectorIds[outputConnector.id] = newOutputId;
                outputConnector.id = oldConnectorIds[newOutputId];
            });
        });
        document.connections.forEach(function (connector) {
            connector.id = getId();
            connector.inputConnectorId = oldConnectorIds[connector.inputConnectorId];
            connector.outputConnectorId = oldConnectorIds[connector.outputConnectorId];
        });
        return document;
    };
    var fromJson = function (s) {
        var document = JSON.parse(s);
        return document;
    };
    var getConnections = function (document) { return document.connections; };
    var getNodes = function (document) { return document.nodes; };
    var doesAcceptDataType = function (incomingType, outgoingType) {
        // TODO refine using accepts of datatypes in Module
        // for now: always accept "nodox.core.any"
        if (incomingType === 'nodox.modules.core.any' || outgoingType === 'nodox.modules.core.any')
            return true;
        if (outgoingType === incomingType)
            return true;
        return false;
    };
    var canAcceptConnection = function (sourceConnector, targetConnector) {
        if (sourceConnector.connectorType === targetConnector.connectorType)
            return false;
        if (sourceConnector.nodeId === targetConnector.nodeId)
            return false;
        if (sourceConnector.dataType === targetConnector.dataType)
            return true;
        return doesAcceptDataType(sourceConnector.dataType, targetConnector.dataType);
    };
    var addNode = function (document, definition) {
        var toInputConnector = function (nodeId) { return function (inputDefinition) { return ({
            id: getId(),
            nodeId: nodeId,
            dataType: inputDefinition.dataType,
            name: inputDefinition.name,
            definitionFullName: definition.fullName,
            connectorType: types_1.ConnectorType.input
        }); }; };
        var toOutputConnector = function (nodeId) { return function (outputDefinition) { return ({
            id: getId(),
            connectorType: types_1.ConnectorType.output,
            dataType: outputDefinition.dataType,
            nodeId: nodeId
        }); }; };
        var id = getId();
        var node = {
            id: id,
            name: definition.name,
            definitionFullName: definition.fullName,
            inputs: definition.inputs.map(toInputConnector(id)),
            outputs: definition.outputs.map(toOutputConnector(id)),
            icon: definition.icon
        };
        document.nodes.push(node);
        return node;
    };
    var deleteNodes = function (document, nodes) {
        nodes.forEach(function (n) { return deleteNode(document, n); });
    };
    var deleteNode = function (document, node) {
        document.connections.filter(function (connection) {
            return __spreadArray(__spreadArray([], node.inputs.map(function (input) { return input.connectionId; })), node.outputs.map(function (output) { return output.connectionId; })).includes(connection.id);
        })
            .forEach(function (connection) {
            removeConnection(document, connection.id);
        });
        document.nodes.splice(document.nodes.indexOf(node), 1);
    };
    var service = {
        getConnections: getConnections,
        getDefinition: getDefinition,
        addNode: addNode,
        canAcceptConnection: canAcceptConnection,
        connect: connect,
        createNewDocument: createNewDocument,
        deleteNode: deleteNode,
        deleteNodes: deleteNodes,
        fromJson: fromJson,
        getConnector: getConnector,
        getInput: getInput,
        getModules: getModules,
        getNode: getNode,
        getNodeFromConnector: getNodeFromConnector,
        getNodes: getNodes,
        getOutput: getOutput,
        indexOfConnector: indexOfConnector,
        reAssignIds: reAssignIds,
        registerModule: registerModule,
        removeConnection: removeConnection
    };
    return service;
};
exports.create = create;
<commit_msg>fixed getOutput<commit_after>"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
    for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
        to[j] = from[i];
    return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = exports.uuidIdProvider = void 0;
var uuid_1 = require("uuid");
var types_1 = require("./types");
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
var uuidIdProvider = function () { return uuid_1.v4(); };
exports.uuidIdProvider = uuidIdProvider;
var create = function (getId) {
    var modules = [];
    var getDefinitionLookup = function () { return modules.reduce(function (definitionLookup, module) {
        return module.definitions.reduce(function (lookup, definition) {
            lookup[definition.fullName] = definition;
            return lookup;
        }, definitionLookup);
    }, {}); };
    var getDefinition = function (fullName) { return getDefinitionLookup()[fullName]; };
    var registerModule = function (module) {
        module.definitions.forEach(function (definition) {
            definition.icon = definition.icon || 'nodox:core_nodox';
            var existingDef = getDefinition(definition.fullName);
            if (existingDef) {
                throw new Error("duplicate definition (" + definition.fullName + "): " + module.name + " and " + existingDef.moduleName);
            }
        });
        var moduleNameSpaces = modules.map(function (m) { return m.namespace; });
        module.dependencies.forEach(function (dependency) {
            if (!moduleNameSpaces.includes(dependency)) {
                throw new Error("Module '" + module.namespace + "' dependency not met: " + dependency);
            }
        });
        modules.push(module);
    };
    var getModules = function () { return modules; };
    var byId = function (id) { return function (item) { return id === item.id; }; };
    var getNode = function (document, nodeId) { return document.nodes.find(byId(nodeId)); };
    var getConnection = function (document, connectionId) { return document.connections.find(byId(connectionId)); };
    var getInput = function (document, inputId) {
        var node = document.nodes.find(function (node) { return node.inputs.find(byId(inputId)) !== undefined; });
        return { node: node, connector: node === null || node === void 0 ? void 0 : node.inputs.find(byId(inputId)) };
    };
    var getOutput = function (document, outputId) {
        var node = document.nodes.find(function (node) { return node.outputs.find(byId(outputId)) !== undefined; });
        return { node: node, connector: node === null || node === void 0 ? void 0 : node.outputs.find(byId(outputId)) };
    };
    var getConnector = function (document, id) {
        var _a = getInput(document, id), node = _a.node, connector = _a.connector;
        return connector !== undefined ? { node: node, connector: connector } : getOutput(document, id);
    };
    var indexOfConnector = function (node, connector) {
        var index = node.inputs.findIndex(byId(connector.id));
        return index > -1 ? index : node.outputs.findIndex(byId(connector.id));
    };
    var getNodeFromConnector = function (document, connector) {
        var node = getNode(document, connector.nodeId);
        return node;
    };
    var removeConnection = function (document, connectionId) {
        var connection = getConnection(document, connectionId);
        if (connection !== undefined) {
            var input = getInput(document, connection.inputConnectorId).connector;
            if (input !== undefined) {
                delete input.connectionId;
            }
            var output = getOutput(document, connection.outputConnectorId).connector;
            if (output !== undefined) {
                delete output.connectionId;
            }
            var index = document.connections.indexOf(connection);
            if (index > -1) {
                document.connections.splice(index, 1);
            }
        }
    };
    var connect = function (document, firstConnector, secondConnector) {
        var _a = firstConnector.connectorType === types_1.ConnectorType.input
            ? { inputConnector: firstConnector, outputConnector: secondConnector }
            : { inputConnector: secondConnector, outputConnector: firstConnector }, inputConnector = _a.inputConnector, outputConnector = _a.outputConnector;
        if (outputConnector.connectionId !== types_1.ConnectorType.output || !canAcceptConnection(outputConnector, inputConnector)) {
            return undefined;
        }
        var currentInputConnections = document
            .connections
            .filter(function (connection) { return connection.inputConnectorId === inputConnector.id; })
            .map(function (connection) { return connection.id; });
        var connection = {
            id: getId(),
            inputConnectorId: inputConnector.id,
            outputConnectorId: outputConnector.id
        };
        inputConnector.connectionId = connection.id;
        currentInputConnections.forEach(function (id) {
            removeConnection(document, id);
        });
        document.connections.push(connection);
        return connection;
    };
    var createNewDocument = function (metaData) {
        var newDocument = {
            id: getId(),
            name: 'New Nodox document',
            connections: [],
            nodes: [],
            metaData: metaData
        };
        return newDocument;
    };
    /**
     * Assigns new ids to document, nodes, node inputs, node outputs and connections
     * used for cloning a document
     * @param document
     */
    var reAssignIds = function (document) {
        document.id = getId();
        document.name += '.cloned';
        var oldConnectorIds = {};
        document.nodes.forEach(function (n) {
            var newId = getId();
            oldConnectorIds[n.id] = newId;
            n.id = newId;
            n.inputs.forEach(function (inputConnector) {
                var newInputId = getId();
                inputConnector.nodeId = n.id;
                oldConnectorIds[inputConnector.id] = newInputId;
                inputConnector.id = newInputId;
            });
            n.outputs.forEach(function (outputConnector) {
                var newOutputId = getId();
                outputConnector.nodeId = n.id;
                oldConnectorIds[outputConnector.id] = newOutputId;
                outputConnector.id = oldConnectorIds[newOutputId];
            });
        });
        document.connections.forEach(function (connector) {
            connector.id = getId();
            connector.inputConnectorId = oldConnectorIds[connector.inputConnectorId];
            connector.outputConnectorId = oldConnectorIds[connector.outputConnectorId];
        });
        return document;
    };
    var fromJson = function (s) {
        var document = JSON.parse(s);
        return document;
    };
    var getConnections = function (document) { return document.connections; };
    var getNodes = function (document) { return document.nodes; };
    var doesAcceptDataType = function (incomingType, outgoingType) {
        // TODO refine using accepts of datatypes in Module
        // for now: always accept "nodox.core.any"
        if (incomingType === 'nodox.modules.core.any' || outgoingType === 'nodox.modules.core.any')
            return true;
        if (outgoingType === incomingType)
            return true;
        return false;
    };
    var canAcceptConnection = function (sourceConnector, targetConnector) {
        if (sourceConnector.connectorType === targetConnector.connectorType)
            return false;
        if (sourceConnector.nodeId === targetConnector.nodeId)
            return false;
        if (sourceConnector.dataType === targetConnector.dataType)
            return true;
        return doesAcceptDataType(sourceConnector.dataType, targetConnector.dataType);
    };
    var addNode = function (document, definition) {
        var toInputConnector = function (nodeId) { return function (inputDefinition) { return ({
            id: getId(),
            nodeId: nodeId,
            dataType: inputDefinition.dataType,
            name: inputDefinition.name,
            definitionFullName: definition.fullName,
            connectorType: types_1.ConnectorType.input
        }); }; };
        var toOutputConnector = function (nodeId) { return function (outputDefinition) { return ({
            id: getId(),
            connectorType: types_1.ConnectorType.output,
            dataType: outputDefinition.dataType,
            nodeId: nodeId
        }); }; };
        var id = getId();
        var node = {
            id: id,
            name: definition.name,
            definitionFullName: definition.fullName,
            inputs: definition.inputs.map(toInputConnector(id)),
            outputs: definition.outputs.map(toOutputConnector(id)),
            icon: definition.icon
        };
        document.nodes.push(node);
        return node;
    };
    var deleteNodes = function (document, nodes) {
        nodes.forEach(function (n) { return deleteNode(document, n); });
    };
    var deleteNode = function (document, node) {
        document.connections.filter(function (connection) {
            return __spreadArray(__spreadArray([], node.inputs.map(function (input) { return input.connectionId; })), node.outputs.map(function (output) { return output.connectionId; })).includes(connection.id);
        })
            .forEach(function (connection) {
            removeConnection(document, connection.id);
        });
        document.nodes.splice(document.nodes.indexOf(node), 1);
    };
    var service = {
        getConnections: getConnections,
        getDefinition: getDefinition,
        addNode: addNode,
        canAcceptConnection: canAcceptConnection,
        connect: connect,
        createNewDocument: createNewDocument,
        deleteNode: deleteNode,
        deleteNodes: deleteNodes,
        fromJson: fromJson,
        getConnector: getConnector,
        getInput: getInput,
        getModules: getModules,
        getNode: getNode,
        getNodeFromConnector: getNodeFromConnector,
        getNodes: getNodes,
        getOutput: getOutput,
        indexOfConnector: indexOfConnector,
        reAssignIds: reAssignIds,
        registerModule: registerModule,
        removeConnection: removeConnection
    };
    return service;
};
exports.create = create;
<|endoftext|>


<commit_before>/*
 *   Copyright 2012 OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

/**
 * Workspace query
 */
var Query = Backbone.Model.extend({

    formatter: Settings.CELLSET_FORMATTER,
    properties: null,

    initialize: function(args, options) {
        // Save cube
        _.extend(this, options);

        // Bind `this`
        _.bindAll(this, "run", "move_dimension", "reflect_properties");

        // Generate a unique query id
        this.uuid = 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
            function (c) {
                var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            }).toUpperCase();

        // Initialize properties, action handler, and result handler
        this.action = new QueryAction({}, { query: this });
        this.result = new Result({ limit: Settings.RESULT_LIMIT }, { query: this });
        this.scenario = new QueryScenario({}, { query: this });

        this.set({type:'QM'});
    },

    parse: function(response) {
        // Assign id so Backbone knows to PUT instead of POST
        this.id = this.uuid;

        this.set({
            connection: response.cube.connectionName,
                catalog: response.cube.catalogName,
                schema: response.cube.schemaName,
                cube: encodeURIComponent(response.cube.name),
                axes: response.saikuAxes,
                type: response.type
        });

        if (typeof response.properties != "undefined" && "saiku.ui.formatter" in response.properties) {
            this.set({formatter : response.properties['saiku.ui.formatter']});
        }

        this.properties = new Properties(response.properties, { query: this });
        this.reflect_properties();
    },

    reflect_properties: function() {
        this.workspace.trigger('properties:loaded');
    },

    setProperty: function(key, value) {
        if (typeof this.properties != "undefined" && this.properties.properties ) {
            this.properties.properties[key] = value;
        }
    },

    run: function(force, mdx) {
        // Check for automatic execution
        Saiku.ui.unblock();
        if (typeof this.properties != "undefined" && this.properties.properties['saiku.olap.query.automatic_execution'] === 'false'&&
            ! (force === true)) {
            return;
        }

        $(this.workspace.el).find(".workspace_results_info").empty();
        this.workspace.trigger('query:run');
        this.result.result = null;
        // TODO - Validate query
        // maybe we should sync it with the backend query JSON?
        // this definitely needs improvement
        var rows = 0;
        var columns = 0;
        if (this.get('type') != "MDX") {
            if (Settings.MODE == "view" || Settings.MODE == "table") {
                var axes = this.get('axes');
                if (axes) {
                    for (var axis_iter = 0; axis_iter < axes.length; axis_iter++) {
                        var axis = axes[axis_iter];
                        if (axis.name && axis.name == "ROWS") {
                            rows = axis.dimensionSelections.length;
                        }
                        if (axis.name && axis.name == "COLUMNS") {
                            columns = axis.dimensionSelections.length;
                        }
                    }
                }
            } else {
                rows = $(this.workspace.el).find('.rows ul li').size();
                columns = $(this.workspace.el).find('.columns ul li').size();
            }

            if (rows == 0 || columns == 0) {
                $(this.workspace.table.el)
                    .html('
You need to put at least one level or measure on Columns and Rows for a valid query.
');
				Saiku.i18n.translate();
                return;
            }
        }

        // Run it
        $(this.workspace.table.el)
            .html('
   Running query...
');
        this.workspace.trigger('query:fetch');
		Saiku.i18n.translate();
            // x
        if (this.get('type')  == "MDX" && mdx != null) {
            this.result.save({ mdx: mdx});
        } else {
            this.result.fetch();
        }
    },

    move_dimension: function(dimension, target, index) {
        $(this.workspace.el).find('.run').removeClass('disabled_toolbar');
        var url = "/axis/" + target + "/dimension/" + dimension;

        this.action.post(url, {
            data: {
                position: index
            },

            success: function() {
                if (('MODE' in Settings && (Settings.MODE == 'view' || Settings.MODE == 'table')) || (typeof this.query.properties != "undefined" && this.query.properties
                    .properties['saiku.olap.query.automatic_execution'] === 'true')) {
                    this.query.run(true);
                }
            }
        });
    },

    url: function() {
        return encodeURI(Saiku.session.username + "/query/" + this.uuid);
    }
});
<commit_msg>new query validation<commit_after>/*
 *   Copyright 2012 OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

/**
 * Workspace query
 */
var Query = Backbone.Model.extend({

    formatter: Settings.CELLSET_FORMATTER,
    properties: null,

    initialize: function(args, options) {
        // Save cube
        _.extend(this, options);

        // Bind `this`
        _.bindAll(this, "run", "move_dimension", "reflect_properties");

        // Generate a unique query id
        this.uuid = 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
            function (c) {
                var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            }).toUpperCase();

        // Initialize properties, action handler, and result handler
        this.action = new QueryAction({}, { query: this });
        this.result = new Result({ limit: Settings.RESULT_LIMIT }, { query: this });
        this.scenario = new QueryScenario({}, { query: this });

        this.set({type:'QM'});
    },

    parse: function(response) {
        // Assign id so Backbone knows to PUT instead of POST
        this.id = this.uuid;

        this.set({
            connection: response.cube.connectionName,
                catalog: response.cube.catalogName,
                schema: response.cube.schemaName,
                cube: encodeURIComponent(response.cube.name),
                axes: response.saikuAxes,
                type: response.type
        });

        if (typeof response.properties != "undefined" && "saiku.ui.formatter" in response.properties) {
            this.set({formatter : response.properties['saiku.ui.formatter']});
        }

        this.properties = new Properties(response.properties, { query: this });
        this.reflect_properties();
    },

    reflect_properties: function() {
        this.workspace.trigger('properties:loaded');
    },

    setProperty: function(key, value) {
        if (typeof this.properties != "undefined" && this.properties.properties ) {
            this.properties.properties[key] = value;
        }
    },

    run: function(force, mdx) {
        // Check for automatic execution
        Saiku.ui.unblock();
        if (typeof this.properties != "undefined" && this.properties.properties['saiku.olap.query.automatic_execution'] === 'false'&&
            ! (force === true)) {
            return;
        }

        $(this.workspace.el).find(".workspace_results_info").empty();
        this.workspace.trigger('query:run');
        this.result.result = null;
        // TODO - Validate query
        // maybe we should sync it with the backend query JSON?
        // this definitely needs improvement
        if (this.get('type') != "MDX") {
            var rows = $(this.workspace.el).find('.rows ul li').size();
            var columns = $(this.workspace.el).find('.columns ul li').size();
            if ((rows == 0 && columns == 0) && !this.workspace.other_dimension) {
                var axes = this.get('axes');
                if (axes) {
                    for (var axis_iter = 0; axis_iter < axes.length; axis_iter++) {
                        var axis = axes[axis_iter];
                        if (axis.name && axis.name == "ROWS") {
                            rows = axis.dimensionSelections.length;
                        }
                        if (axis.name && axis.name == "COLUMNS") {
                            columns = axis.dimensionSelections.length;
                        }
                    }
                }
            }
            if (rows == 0 || columns == 0) {
                $(this.workspace.table.el)
                    .html('
You need to put at least one level or measure on Columns and Rows for a valid query.
');
                $(this.workspace.chart.processing).hide();
                Saiku.i18n.translate();
                return;
            }
        }

        // Run it
        $(this.workspace.table.el)
            .html('
   Running query...
');
        this.workspace.trigger('query:fetch');
		Saiku.i18n.translate();
            // x
        if (this.get('type')  == "MDX" && mdx != null) {
            this.result.save({ mdx: mdx});
        } else {
            this.result.fetch();
        }
    },

    move_dimension: function(dimension, target, index) {
        $(this.workspace.el).find('.run').removeClass('disabled_toolbar');
        var url = "/axis/" + target + "/dimension/" + dimension;

        this.action.post(url, {
            data: {
                position: index
            },

            success: function() {
                if (('MODE' in Settings && (Settings.MODE == 'view' || Settings.MODE == 'table')) || (typeof this.query.properties != "undefined" && this.query.properties
                    .properties['saiku.olap.query.automatic_execution'] === 'true')) {
                    this.query.run(true);
                }
            }
        });
    },

    url: function() {
        return encodeURI(Saiku.session.username + "/query/" + this.uuid);
    }
});
<|endoftext|>