<commit_before>/**!
 * Animated Recent Signers for Greenpeace Action Template v0.3
 * INCOMPLETE
 * @name            p3.recent_signers.js
 * @fileOverview    Displays the most recent pledge signers, queued and
 *                  animated
 * @copyright       Copyright 2013, Greenpeace International
 * @license         MIT License (opensource.org/licenses/MIT)
 * @version         0.1.0
 * @author          Ray Walker <hello@raywalker.it>
 * @requires        jQuery 1.6+,
 *                  Modernizr,
 * @example         $.p3.recent_signers('#action-recent-signers'[, options]);
 * @todo            EVENT DRIVEN DATA UPDATES:  trigger fetches & parsing externally
 *
 */
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:true, curly:true, browser:true, devel:true, jquery:true, indent:4, maxerr:50 */
/*global Modernizr */

(function($, M, window, undef) {
    'use strict';

    var _p3 = $.p3 || {},
        defaults = {
            jsonURL: 'https://www.greenpeace.org/api/p3/pledge/pledges.json',
            /* parameters to be added to the request url */
            params: {},
            /* set to true to delay execution until externally triggered by event */
            eventDriven: false,
            /* trigger this event to fetch JSON data from the endpoint */
            fetchDataEvent: 'fetchPledgeData',
            /* trigger this event if you have fetched data externally and just
             * want to parse and update display */
            fetchCompleteEvent: 'fetchPledgeDataComplete',
            /* delay in milliseconds between signer check updates */
            updateInterval: 5000,
            /* interval between users added to the recent signer list from last
             * update */
            userQueueInterval: 750,
            /* maximum number of users to display at once, excess users are hidden
             * and then removed from the DOM */
            maxUsers: 8,
            /* number of times to check the server for new signers after the first
             * set to 0 to disable updates */
            maxRefreshes: 30,
            /* selector for the country dropdown to map country codes to names */
            countrySelector: '#UserCountry',
            /* stop processing if there is an error communicating with the server */
            abortOnError: false
        };

    // Custom selector to match country codes to country names
    $.expr[":"].valueNoCase = function(el, i, m) {
        var search = m[3];
        if (!search) {
            return false;
        }

        return $(el).prop('value').toLowerCase() === search.toLowerCase();
    };

    _p3.recent_signers = function(el, options) {
        var config = $.extend(true, defaults, options),
            $el = $(el),
            $ul = false,
            request = $.p3.request(config.jsonURL),
            users = [],
            timer = false,
            refreshNum = 0,
            prefix = '$.p3.recent_signers :: ',
            pledgeQueue = {
                running: false,
                delay: config.userQueueInterval,
                actions: [],
                callback: function() {
                },
                step: function() {
                    if (pledgeQueue.actions.length) {
                        try {
                            pledgeQueue.actions.pop()();
                        } catch (e) {
                            console.log(e);
                        }
                    } else {
                        pledgeQueue.running = false;
                    }
                },
                run: function() {
                    pledgeQueue.running = true;
                    if (pledgeQueue.actions.length) {
                        pledgeQueue.step();
                        setTimeout(pledgeQueue.run, pledgeQueue.delay);
                    } else {
                        pledgeQueue.running = false;
                        pledgeQueue.callback();
                    }
                }
            },
            fetchJSON = function() {
                if (pledgeQueue.running) {
                    // Still executing last update, restart timer
                    clearTimeout(timer);
                    timer = setTimeout(function() {
                        fetchJSON();
                    }, config.updateInterval);
                    // and exit
                    return false;
                }

                var params = $.extend(true, request.parameters, config.params),
                    response;

                $.getJSON(request.url, params, function(json) {
                    response = json;
                }).fail(function() {
                    var message = prefix + 'Failed to load JSON from "' + request.url + '"';

                    if (config.abortOnError) {
                        throw new Error(message);
                    } else {
                        console.warn(message);
                    }
                }).complete(function () {
                    parsePledgeData(response);
                });

            },
            parsePledgeData = function(json) {
                // Load from the parameter if set,
                // else load from the data stored in an element if eventDriven
                var jsonData = (undef === json) ? $(config.dataElement).data(config.dataNamespace) : json;

                if (!jsonData) {
                    if (config.abortOnError) {
                        throw new Error(prefix + 'JSON data invalid');
                    } else {
                        return;
                    }
                }

                // Add fetch first, since array is popped not shifted
                if (refreshNum++ < config.maxRefreshes) {
                    pledgeQueue.actions.push(function() {
                        clearTimeout(timer);
                        timer = setTimeout(function() {
                            fetchJSON();
                        }, config.updateInterval);
                    });
                }

                $.each(jsonData.pledges, function(i, pledge) {

                    if (users[pledge.user.id]) {
                        // Already added, exit $.each
                        return false;
                    } else {
                        // Store this ID
                        users[pledge.user.id] = true;
                    }

                    if (pledge.user.dont_display_name === true) {
                        // Skip to next pledge ...
                        return true;
                    }

                    pledgeQueue.actions.push(function() {
                        // Enqueue this user
                        showUser(pledge.user);
                    });

                });

                // Update existing timestamps
                pledgeQueue.actions.push(function() {
                    updateTimeStamps();
                });

                // Show all pledges in the queue
                pledgeQueue.run();

            },
            /**
             * Retrieves human readable time string from timestamp
             * @param {string} timestamp
             * @returns {unresolved}
             */
            getTimeString = function(time) {
                if (time) {
                    return $.timeago(time);
                }
            },
            getCountryString = function(country) {
                return $(config.countrySelector + ' option:valueNoCase(' + country + ')').text();
            },
            showUser = function(user) {
                var $li = $('
' + getTimeString(user.created) + '' + user.firstname +
                    ' ' + user.lastname + '' +
                    getCountryString(user.country) + '
');

                // Add to DOM
                $ul.prepend($li);

                // And show
                $li.show(350);

                // Remove any excess users
                if (config.maxUsers && $('li', $ul).length > config.maxUsers) {
                    $('li:last', $ul).hide(350).remove();
                }
            },
            updateTimeStamps = function() {
                $('.since', $ul).each(function() {
                    var $this = $(this);
                    $this.text(getTimeString($this.attr('data-since')));
                });
            };

        // initialise and run

        if (config.updateInterval < 5000) {
            // Update interval sanity check
            config.updateInterval = 5000;
        }

        $ul = $('ul:first', $el);
        if (!$ul.length) {
            $ul = $('

');
            $el.append($ul);
        }

        M.load({
            test: window.JSON,
            nope: [
                'js/vendor/json.min.js'
            ],
            complete: function() {
                // Apply human readable string to existing timestamps
                updateTimeStamps();

                if (config.eventDriven) {
                    // Event driven fetch and processing means we can decouple data
                    // from this plugin, allowing us to reuse the data without
                    // performing multiple requests
                    $(window).on(config.fetchDataEvent, function() {
                        // trigger this event to initiate a fetch
                        fetchJSON();
                    });

                    $(window).on(config.fetchCompleteEvent, function() {
                        // trigger this event if the JSON has already been fetched and is ready to parse
                        parsePledgeData();
                    });
                } else {
                    fetchJSON();
                }
            }
        });

    };

    $.p3 = _p3;

}(jQuery, Modernizr, this));
<commit_msg>p3.recent_signers.js - 0.1.1 - added configuration options for time element and data attributes<commit_after>/**!
 * Animated Recent Signers for Greenpeace Action Template v0.3
 * @name            p3.recent_signers.js
 * @fileOverview    Displays the most recent pledge signers, queued and
 *                  animated
 * @copyright       Copyright 2013, Greenpeace International
 * @license         MIT License (opensource.org/licenses/MIT)
 * @version         0.1.1
 * @author          Ray Walker <hello@raywalker.it>
 * @requires        jQuery 1.6+,
 *                  Modernizr,
 * @example         $.p3.recent_signers('#action-recent-signers'[, options]);
 * @todo            EVENT DRIVEN DATA UPDATES:
 *                      trigger fetches & parsing externally
 *                      to reuse data and minimise API requests per page
 *
 */
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:true, curly:true, browser:true, devel:true, jquery:true, indent:4, maxerr:50 */
/*global Modernizr */

(function($, M, window, undef) {
    'use strict';

    var _p3 = $.p3 || {},
        defaults = {
            jsonURL: 'https://www.greenpeace.org/api/p3/pledge/pledges.json',
            /* parameters to be added to the request url */
            params: {},
            /* selects which element holds the time data attribute */
            timeSelector: '.since',
            /* selects which attribute contains timestamps */
            timeDataAttr: 'data-since',
            /* selector for the country dropdown to map country codes to names */
            countrySelector: '#UserCountry',
            /* set to true to delay execution until externally triggered by event */
            eventDriven: false,
            /* trigger this event to fetch JSON data from the endpoint */
            fetchDataEvent: 'fetchPledgeData',
            /* trigger this event if you have fetched data externally and just
             * want to parse and update display */
            fetchCompleteEvent: 'fetchPledgeDataComplete',
            /* delay in milliseconds between signer check updates */
            updateInterval: 5000,
            /* interval between users added to the recent signer list from last
             * update */
            userQueueInterval: 750,
            /* maximum number of users to display at once, excess users are hidden
             * and then removed from the DOM */
            maxUsers: 8,
            /* number of times to check the server for new signers after the first
             * set to 0 to disable updates */
            maxRefreshes: 30,
            /* stop processing if there is an error */
            abortOnError: false
        };

    _p3.recent_signers = function(el, options) {
        var config = $.extend(true, defaults, options),
            $el = $(el),
            $ul = false,
            request = $.p3.request(config.jsonURL),
            users = [],
            timer = false,
            refreshNum = 0,
            prefix = '$.p3.recent_signers :: ',
            pledgeQueue = {
                running: false,
                delay: config.userQueueInterval,
                actions: [],
                callback: function() {
                },
                step: function() {
                    if (pledgeQueue.actions.length) {
                        try {
                            pledgeQueue.actions.pop()();
                        } catch (e) {
                            console.log(e);
                        }
                    } else {
                        pledgeQueue.running = false;
                    }
                },
                run: function() {
                    pledgeQueue.running = true;
                    if (pledgeQueue.actions.length) {
                        pledgeQueue.step();
                        setTimeout(pledgeQueue.run, pledgeQueue.delay);
                    } else {
                        pledgeQueue.running = false;
                        pledgeQueue.callback();
                    }
                }
            },
            fetchJSON = function() {
                if (pledgeQueue.running) {
                    // Still executing last update, restart timer
                    clearTimeout(timer);
                    timer = setTimeout(function() {
                        fetchJSON();
                    }, config.updateInterval);
                    // and exit
                    return false;
                }

                var params = $.extend(true, request.parameters, config.params),
                    response;

                $.getJSON(request.url, params, function(json) {
                    response = json;
                }).fail(function() {
                    var message = prefix + 'Failed to load JSON from "' + request.url + '"';

                    if (config.abortOnError) {
                        throw new Error(message);
                    } else {
                        console.warn(message);
                    }
                }).complete(function () {
                    parsePledgeData(response);
                });

            },
            parsePledgeData = function(json) {
                // Load from the parameter if set,
                // else load from the data stored in an element if eventDriven
                var jsonData = (undef === json) ? $(config.dataElement).data(config.dataNamespace) : json;

                if (!jsonData) {
                    if (config.abortOnError) {
                        throw new Error(prefix + 'JSON data invalid');
                    } else {
                        return;
                    }
                }

                // Add fetch first, since array is popped not shifted
                if (refreshNum++ < config.maxRefreshes) {
                    pledgeQueue.actions.push(function() {
                        clearTimeout(timer);
                        timer = setTimeout(function() {
                            fetchJSON();
                        }, config.updateInterval);
                    });
                }

                $.each(jsonData.pledges, function(i, pledge) {

                    if (users[pledge.user.id]) {
                        // Already added, exit $.each
                        return false;
                    } else {
                        // Store this ID
                        users[pledge.user.id] = true;
                    }

                    if (pledge.user.dont_display_name === true) {
                        // Skip to next pledge ...
                        return true;
                    }

                    pledgeQueue.actions.push(function() {
                        // Enqueue this user
                        showUser(pledge.user);
                    });

                });

                // Update existing timestamps
                pledgeQueue.actions.push(function() {
                    updateTimeStamps();
                });

                // Show all pledges in the queue
                pledgeQueue.run();

            },
            /**
             * Retrieves human readable time string from timestamp
             * @param {string} timestamp
             * @returns {unresolved}
             */
            getTimeString = function(time) {
                if (time) {
                    return $.timeago(time);
                }
            },
            getCountryString = function(country) {
                return $(config.countrySelector + ' option:valueNoCase(' + country + ')').text();
            },
            showUser = function(user) {
                var $li = $('
' + getTimeString(user.created) + '' + user.firstname +
                    ' ' + user.lastname + '' +
                    getCountryString(user.country) + '
');

                // Add to DOM
                $ul.prepend($li);

                // And show
                $li.show(350);

                // Remove any excess users
                if (config.maxUsers && $('li', $ul).length > config.maxUsers) {
                    $('li:last', $ul).hide(350).remove();
                }
            },
            updateTimeStamps = function() {
                $(config.timeSelector, $ul).each(function() {
                    var $this = $(this);
                    $this.text(getTimeString($this.attr(config.timeDataAttr)));
                });
            };

        // initialise and run

        if (config.updateInterval < 5000) {
            // Update interval sanity check
            config.updateInterval = 5000;
        }

        $ul = $('ul:first', $el);
        if (!$ul.length) {
            $ul = $('

');
            $el.append($ul);
        }

        M.load({
            test: window.JSON,
            nope: [
                'js/vendor/json.min.js'
            ],
            complete: function() {
                // Apply human readable string to existing timestamps
                updateTimeStamps();

                if (config.eventDriven) {
                    // Event driven fetch and processing means we can decouple data
                    // from this plugin, allowing us to reuse the data without
                    // performing multiple requests
                    $(window).on(config.fetchDataEvent, function() {
                        // trigger this event to initiate a fetch
                        fetchJSON();
                    });

                    $(window).on(config.fetchCompleteEvent, function() {
                        // trigger this event if the JSON has already been fetched and is ready to parse
                        parsePledgeData();
                    });
                } else {
                    fetchJSON();
                }
            }
        });

    };

    $.p3 = _p3;

}(jQuery, Modernizr, this));
<|endoftext|>


<commit_before>import GLExtensionsManager from '../low_level/core/GLExtensionsManager';
import Geometry from '../low_level/geometries/Geometry';
import GLBoostObject from '../low_level/core/GLBoostObject';

/**
 * en: This class take a role as operator of rendering process. In order to render images to canvas, this Renderer class gathers other elements' data, decides a plan of drawing process, and then just execute it.

 * ja: このクラスはレンダリングプロセスの制御を司ります。Canvasにイメージをレンダリングするために、このRendererクラスは他の要素のデータを集め、描画プロセスの計画を決定し、実行します。
 */
export default class Renderer extends GLBoostObject {
  constructor(glBoostContext, parameters) {
    super(glBoostContext);
    var _clearColor = parameters.clearColor;

    var gl = this._glContext.gl;

    this._glBoostContext.reflectGlobalGLState();

    gl.clearColor( _clearColor.red, _clearColor.green, _clearColor.blue, _clearColor.alpha );
  }

  /**
   * en: draw elements of the scene.

   * ja: sceneが持つオブジェクトを描画します
   * @param {Scene} scene a instance of Scene class
   */
  draw(expression) {
    expression.renderPasses.forEach((renderPass, index)=>{
      if (!renderPass.isEnableToDraw || !renderPass.scene) {
        return;
      }

      var camera = false;
      renderPass.scene.cameras.forEach((elm)=> {
        if (elm.isMainCamera(renderPass.scene)) {
          camera = elm;
        }
      });

      let lights = renderPass.scene.lights;

      renderPass.doSomethingBeforeRender(camera ? true:false, lights);

      var glContext = this._glContext;
      var gl = glContext.gl;
      var glem = GLExtensionsManager.getInstance(this._glContext);

      // set render target buffers for each RenderPass.
      /*
      if (renderPass.fbo && renderPass.isRenderTargetTexturesIfSet) {
        gl.bindTexture(gl.TEXTURE_2D, null);
        gl.bindFramebuffer(gl.FRAMEBUFFER, renderPass.fbo);
      } else {
        glem.drawBuffers(gl, [gl.BACK]);
      }
      */
      if (renderPass.fbo && renderPass.isRenderTargetTexturesIfSet) {
        gl.bindFramebuffer(gl.FRAMEBUFFER, renderPass.fbo);
      }

      glem.drawBuffers(gl, renderPass.buffersToDraw);
      //glem.readBuffer(gl, renderPass.buffersToDraw);

      if (renderPass.viewport) {
        gl.viewport(renderPass.viewport.x, renderPass.viewport.y, renderPass.viewport.z, renderPass.viewport.w)
      } else {
        if (camera) {
          let deltaWidth = glContext.canvasHeight*camera.aspect - glContext.canvasWidth;
          gl.viewport(-deltaWidth/2, 0, glContext.canvasHeight*camera.aspect, glContext.canvasHeight);
        } else {
          gl.viewport(0, 0, glContext.canvasWidth, glContext.canvasHeight);
        }
      }

      this._clearBuffer(gl, renderPass);

      // draw opacity meshes.
      var opacityMeshes = renderPass.opacityMeshes;
      opacityMeshes.forEach((mesh)=> {
        if (mesh.isVisible) {
          mesh.draw(expression, lights, camera, renderPass.scene, index);
        }
      });

      if (camera) {
        renderPass.sortTransparentMeshes(camera);
      }
      // draw transparent meshes.
      var transparentMeshes = renderPass.transparentMeshes;
      transparentMeshes.forEach((mesh)=> {
        if (mesh.isVisible) {
          mesh.draw(expression, lights, camera, renderPass.scene, index);
        }
      });

      let gizmos = renderPass.gizmos;
      for (let gizmo of gizmos) {
        if (gizmo.isVisible) {
          gizmo.mesh.draw(expression, lights, camera, renderPass.scene, index);
        }
      }

      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
//      glem.drawBuffers(gl, [gl.BACK]);

      renderPass.doSomethingAfterRender(camera ? true:false, lights);

    });
  }

  _clearBuffer(gl, renderPass) {
    var clearColor = renderPass.clearColor;
    var clearDepth = renderPass.clearDepth;
    if (clearColor) {
      gl.clearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
    }
    if (clearDepth) {
      gl.clearDepth(clearDepth);
    }

    if (renderPass.buffersToDraw[0] === gl.NONE) {
      {
        gl.clear(gl.DEPTH_BUFFER_BIT);
      }
    } else if (clearColor || clearDepth) {
      gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    } else if (clearColor) {
      gl.clear( gl.COLOR_BUFFER_BIT );
    }
  }

  /**
   * en: clear color/depth/stencil of canvas.

   * ja: canvasのカラー、デプス、ステンシルのいずれか又は全てをクリアします。
   * @param {boolean} color_flg true: clear color, false: don't clear color
   * @param {boolean} depth_flg true: clear depth, false: don't clear depth
   * @param {boolean} stencil_flg  true: clear stencil, false: don't clear stencil
   */
  clearCanvas( color_flg, depth_flg, stencil_flg ) {

    var gl = this._glContext.gl;

    var bufferBits = 0;

    if ( color_flg === void 0 || color_flg ) bufferBits |= gl.COLOR_BUFFER_BIT;
    if ( depth_flg === void 0 || depth_flg ) bufferBits |= gl.DEPTH_BUFFER_BIT;
    if ( stencil_flg === void 0 || stencil_flg ) bufferBits |= gl.STENCIL_BUFFER_BIT;

    gl.clear( bufferBits );

  }

  /**
   * en: Get WebGL context.

   * ja: WebGLコンテキストを取得します。
   * @returns {webglcontext} a context of WebGL
   */
  get glContext() {
    return this._glContext.gl;
  }

  /**
   * en: resize canvas and viewport.

   * ja: canvasとビューポートをリサイズします。
   * @param {number} width en: width to resize, ja: リサイズする幅
   * @param {number} height en: height to resize, ja:リサイズする高さ
   */
  resize(width, height) {
    this._glContext.canvasWidth = width;
    this._glContext.canvasHeight = height;
  }

}
<commit_msg>Fix Renderer<commit_after>import GLExtensionsManager from '../low_level/core/GLExtensionsManager';
import Geometry from '../low_level/geometries/Geometry';
import GLBoostObject from '../low_level/core/GLBoostObject';

/**
 * en: This class take a role as operator of rendering process. In order to render images to canvas, this Renderer class gathers other elements' data, decides a plan of drawing process, and then just execute it.

 * ja: このクラスはレンダリングプロセスの制御を司ります。Canvasにイメージをレンダリングするために、このRendererクラスは他の要素のデータを集め、描画プロセスの計画を決定し、実行します。
 */
export default class Renderer extends GLBoostObject {
  constructor(glBoostContext, parameters) {
    super(glBoostContext);
    var _clearColor = parameters.clearColor;

    var gl = this._glContext.gl;

    this._glBoostContext.reflectGlobalGLState();

    gl.clearColor( _clearColor.red, _clearColor.green, _clearColor.blue, _clearColor.alpha );
  }

  /**
   * en: draw elements of the scene.

   * ja: sceneが持つオブジェクトを描画します
   * @param {Scene} scene a instance of Scene class
   */
  draw(expression) {
    let renderPassTag = '';
    expression.renderPasses.forEach((renderPass, index)=>{
      if (!renderPass.isEnableToDraw || !renderPass.scene) {
        return;
      }
/*
      if (renderPassTag !== renderPass.tag) {
        renderPass.clearAssignShaders();
      }
      renderPassTag = renderPass.tag;
*/
      var camera = false;
      renderPass.scene.cameras.forEach((elm)=> {
        if (elm.isMainCamera(renderPass.scene)) {
          camera = elm;
        }
      });

      let lights = renderPass.scene.lights;

      renderPass.preRender(camera ? true:false, lights);

      var glContext = this._glContext;
      var gl = glContext.gl;
      var glem = GLExtensionsManager.getInstance(this._glContext);

      // set render target buffers for each RenderPass.
      /*
      if (renderPass.fbo && renderPass.isRenderTargetTexturesIfSet) {
        gl.bindTexture(gl.TEXTURE_2D, null);
        gl.bindFramebuffer(gl.FRAMEBUFFER, renderPass.fbo);
      } else {
        glem.drawBuffers(gl, [gl.BACK]);
      }
      */
      if (renderPass.fbo && renderPass.isRenderTargetTexturesIfSet) {
        gl.bindFramebuffer(gl.FRAMEBUFFER, renderPass.fbo);
      }

      glem.drawBuffers(gl, renderPass.buffersToDraw);
      //glem.readBuffer(gl, renderPass.buffersToDraw);

      if (renderPass.viewport) {
        gl.viewport(renderPass.viewport.x, renderPass.viewport.y, renderPass.viewport.z, renderPass.viewport.w)
      } else {
        if (camera) {
          let deltaWidth = glContext.canvasHeight*camera.aspect - glContext.canvasWidth;
          gl.viewport(-deltaWidth/2, 0, glContext.canvasHeight*camera.aspect, glContext.canvasHeight);
        } else {
          gl.viewport(0, 0, glContext.canvasWidth, glContext.canvasHeight);
        }
      }

      this._clearBuffer(gl, renderPass);

      // draw opacity meshes.
      var opacityMeshes = renderPass.opacityMeshes;
      opacityMeshes.forEach((mesh)=> {
        if (mesh.isVisible) {
          mesh.draw(expression, lights, camera, renderPass.scene, index);
        }
      });

      if (camera) {
        renderPass.sortTransparentMeshes(camera);
      }
      // draw transparent meshes.
      var transparentMeshes = renderPass.transparentMeshes;
      transparentMeshes.forEach((mesh)=> {
        if (mesh.isVisible) {
          mesh.draw(expression, lights, camera, renderPass.scene, index);
        }
      });

      let gizmos = renderPass.gizmos;
      for (let gizmo of gizmos) {
        if (gizmo.isVisible) {
          gizmo.mesh.draw(expression, lights, camera, renderPass.scene, index);
        }
      }

      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
//      glem.drawBuffers(gl, [gl.BACK]);

      renderPass.postRender(camera ? true:false, lights);

    });
  }

  _clearBuffer(gl, renderPass) {
    var clearColor = renderPass.clearColor;
    var clearDepth = renderPass.clearDepth;
    if (clearColor) {
      gl.clearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
    }
    if (clearDepth) {
      gl.clearDepth(clearDepth);
    }

    if (renderPass.buffersToDraw[0] === gl.NONE) {
      {
        gl.clear(gl.DEPTH_BUFFER_BIT);
      }
    } else if (clearColor || clearDepth) {
      gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    } else if (clearColor) {
      gl.clear( gl.COLOR_BUFFER_BIT );
    }
  }

  /**
   * en: clear color/depth/stencil of canvas.

   * ja: canvasのカラー、デプス、ステンシルのいずれか又は全てをクリアします。
   * @param {boolean} color_flg true: clear color, false: don't clear color
   * @param {boolean} depth_flg true: clear depth, false: don't clear depth
   * @param {boolean} stencil_flg  true: clear stencil, false: don't clear stencil
   */
  clearCanvas( color_flg, depth_flg, stencil_flg ) {

    var gl = this._glContext.gl;

    var bufferBits = 0;

    if ( color_flg === void 0 || color_flg ) bufferBits |= gl.COLOR_BUFFER_BIT;
    if ( depth_flg === void 0 || depth_flg ) bufferBits |= gl.DEPTH_BUFFER_BIT;
    if ( stencil_flg === void 0 || stencil_flg ) bufferBits |= gl.STENCIL_BUFFER_BIT;

    gl.clear( bufferBits );

  }

  /**
   * en: Get WebGL context.

   * ja: WebGLコンテキストを取得します。
   * @returns {webglcontext} a context of WebGL
   */
  get glContext() {
    return this._glContext.gl;
  }

  /**
   * en: resize canvas and viewport.

   * ja: canvasとビューポートをリサイズします。
   * @param {number} width en: width to resize, ja: リサイズする幅
   * @param {number} height en: height to resize, ja:リサイズする高さ
   */
  resize(width, height) {
    this._glContext.canvasWidth = width;
    this._glContext.canvasHeight = height;
  }

}
<|endoftext|>


<commit_before>(function () {
  angular
    .module("ng-geocoder")
    .directive("ngGeocoder", ngGeocoder);

  ngGeocoder.$inject = ["$timeout", "$templateCache", "ngGeocoderService"];

  function ngGeocoder ($timeout, $templateCache, ngGeocoderService) {
    var DEFAULT_TEMPLATE_URL = "/ng-geocoder/ng-geocoder.html";

    $templateCache.put(DEFAULT_TEMPLATE_URL, INCLUDE_FILE("ng-geocoder.html"));

    var directive = {
      "restrict": "AE",
      "scope": {
        "result": "=ngGeocoder",
        "inputId": "=",
        "wait": "=",
        "minLength": "=",
        "inputClass": "@",
        "placeholder": "@",
        "textSearching": "@",
        "textNoResults": "@",
        "maxHeight": "@"
      },
      "link": link,
      "templateUrl": geocoderTemplate
    };

    return directive;

    function link (scope, element, attributes) {
      var waitTimeout;

      var $el      = element[0];
      var form     = $el.closest("form");
      var input    = $el.querySelector(".ng-geocoder__input");
      var dropdown = $el.querySelector(".ng-geocoder__list");
      var placeId  = attributes.placeId;

      scope.index   = 0;
      scope.query   = "";
      scope.results = [];

      scope.selectItem   = selectItem;
      scope.displayList  = displayList;
      scope.inputKeydown = inputKeydown;

      form.addEventListener("keydown", formKeydown);

      input.addEventListener("blur",           inputBlur);
      input.addEventListener("focus",          inputFocus);
      input.addEventListener("input",          inputChanged);
      input.addEventListener("keydown",        inputKeydown);
      input.addEventListener("compositionend", inputChanged);

      if (placeId) {
        ngGeocoderService.geocodeById(placeId)
          .then(geocodedWithPlaceId);
      }

      function formKeydown (event) {
        var targetIsGeocoderInput = event.target.classList.contains("ng-geocoder__input");

        if (event.keyCode === 13 && targetIsGeocoderInput) {
          event.preventDefault();
          event.stopPropagation();
        }
      }

      function inputBlur (event) {
        $timeout(function () {
          scope.showList = false;
        }, 100);
      }

      function inputFocus (event) {
        scope.$apply(function () {
          scope.showList = true;
        });
      }

      function inputChanged (event) {
        var length = scope.query.length;

        if (length < scope.minLength || scope.isSearching) { return; }

        if (waitTimeout) { $timeout.cancel(waitTimeout); }

        waitTimeout = $timeout(search, scope.wait || 500);
      }

      function inputKeydown (event) {
        if (!event || !event.keyCode) return;

        var enterPressed  = event.keyCode === 13;
        var arrowsPressed = event.keyCode === 38 || event.keyCode === 40;

        if (enterPressed || arrowsPressed) {
          if (arrowsPressed) handleArrowKeys(event.keyCode);
          if (enterPressed)  selectItem(scope.index);

          event.preventDefault();
          event.stopPropagation();

          return false;
        }
      }

      function search () {
        scope.results     = [];
        scope.isEmpty     = false;
        scope.isSearching = true;

        return ngGeocoderService.geocodeByQuery(scope.query, attributes.region)
          .then(geocodeSuccess);
      }

      function geocodeSuccess (results) {
        scope.index       = 0;
        scope.isEmpty     = results.length === 0;
        scope.results     = results;
        scope.showList    = true;
        scope.isSearching = false;
      }

      function geocodedWithPlaceId (results) {
        var result = results[0];

        if (result) {
          scope.query    = result.formatted_address;
          scope.result   = result;

          scope.showList = false;
        }
      }

      function selectItem (index) {
        $timeout(function () {
          scope.index    = index;
          scope.result   = scope.results[index];
          scope.query    = scope.result.formatted_address;

          scope.showList = false;
        }, 0);
      }

      function displayList () {
        return scope.query.length >= scope.minLength && scope.showList;
      }

      function handleArrowKeys(key) {
        var index         = scope.index;
        var resultsLength = scope.results.length;

        var arrowUp   = key === 38;
        var arrowDown = key === 40;

        if (arrowUp && (index - 1 >= 0)) {
          index--;
        }

        if (arrowDown && (index + 1 < resultsLength)) {
          index++;
        }

        scope.$apply(function () {
          scope.index = index;
        });

        if (arrowUp   && scope.results.length) fixArrowUpScroll();
        if (arrowDown && scope.results.length) fixArrowDownScroll();
      }

      function fixArrowUpScroll() {
        var rowTop = dropdownRowTop();
        var height = dropdownRowOffsetHeight(getCurrentRow());

        if (rowTop < height) {
          dropdownScrollTo(rowTop - height);
        }
      }

      function fixArrowDownScroll () {
        var row = getCurrentRow();

        if (getDropdownHeight() < row.getBoundingClientRect().bottom) {
          dropdownScrollTo(dropdownRowOffsetHeight(row));
        }
      }

      function getCurrentRow () {
        return $el.querySelector(".ng-geocoder__list__item--focus");
      }

      function dropdownRowTop () {
        return getCurrentRow().getBoundingClientRect().top - (dropdown.getBoundingClientRect().top + parseInt(getComputedStyle(dropdown).paddingTop, 10));
      }

      function dropdownScrollTo (offset) {
        dropdown.scrollTop = dropdown.scrollTop + offset;
      }

      function getDropdownHeight () {
        return dropdown.getBoundingClientRect().top + parseInt(getComputedStyle(dropdown).maxHeight, 10);
      }

      function dropdownRowOffsetHeight (row) {
        var css = getComputedStyle(row);

        return row.offsetHeight + parseInt(css.marginTop, 10) + parseInt(css.marginBottom, 10);
      }
    }

    function geocoderTemplate (element, attributes) {
      return attributes.templateUrl || DEFAULT_TEMPLATE_URL
    }
  }
})();
<commit_msg>Fix searching message display<commit_after>(function () {
  angular
    .module("ng-geocoder")
    .directive("ngGeocoder", ngGeocoder);

  ngGeocoder.$inject = ["$timeout", "$templateCache", "ngGeocoderService"];

  function ngGeocoder ($timeout, $templateCache, ngGeocoderService) {
    var DEFAULT_TEMPLATE_URL = "/ng-geocoder/ng-geocoder.html";

    $templateCache.put(DEFAULT_TEMPLATE_URL, INCLUDE_FILE("ng-geocoder.html"));

    var directive = {
      "restrict": "AE",
      "scope": {
        "result": "=ngGeocoder",
        "inputId": "=",
        "wait": "=",
        "minLength": "=",
        "inputClass": "@",
        "placeholder": "@",
        "textSearching": "@",
        "textNoResults": "@",
        "maxHeight": "@"
      },
      "link": link,
      "templateUrl": geocoderTemplate
    };

    return directive;

    function link (scope, element, attributes) {
      var waitTimeout;

      var $el      = element[0];
      var form     = $el.closest("form");
      var input    = $el.querySelector(".ng-geocoder__input");
      var dropdown = $el.querySelector(".ng-geocoder__list");
      var placeId  = attributes.placeId;

      scope.index   = 0;
      scope.query   = "";
      scope.results = [];

      scope.selectItem   = selectItem;
      scope.displayList  = displayList;
      scope.inputKeydown = inputKeydown;

      form.addEventListener("keydown", formKeydown);

      input.addEventListener("blur",           inputBlur);
      input.addEventListener("focus",          inputFocus);
      input.addEventListener("input",          inputChanged);
      input.addEventListener("keydown",        inputKeydown);
      input.addEventListener("compositionend", inputChanged);

      if (placeId) {
        ngGeocoderService.geocodeById(placeId)
          .then(geocodedWithPlaceId);
      }

      function formKeydown (event) {
        var targetIsGeocoderInput = event.target.classList.contains("ng-geocoder__input");

        if (event.keyCode === 13 && targetIsGeocoderInput) {
          event.preventDefault();
          event.stopPropagation();
        }
      }

      function inputBlur (event) {
        $timeout(function () {
          scope.showList = false;
        }, 100);
      }

      function inputFocus (event) {
        scope.$apply(function () {
          scope.showList = true;
        });
      }

      function inputChanged (event) {
        var length = scope.query.length;

        if (length < scope.minLength || scope.isSearching) { return; }

        if (waitTimeout) { $timeout.cancel(waitTimeout); }

        waitTimeout = $timeout(search, scope.wait || 500);
      }

      function inputKeydown (event) {
        if (!event || !event.keyCode) return;

        var enterPressed  = event.keyCode === 13;
        var arrowsPressed = event.keyCode === 38 || event.keyCode === 40;

        if (enterPressed || arrowsPressed) {
          if (arrowsPressed) handleArrowKeys(event.keyCode);
          if (enterPressed)  selectItem(scope.index);

          event.preventDefault();
          event.stopPropagation();

          return false;
        }
      }

      function search () {
        scope.$apply(function () {
          scope.results     = [];
          scope.isEmpty     = false;
          scope.isSearching = true;
        });

        return ngGeocoderService.geocodeByQuery(scope.query, attributes.region)
          .then(geocodeSuccess);
      }

      function geocodeSuccess (results) {
        scope.index       = 0;
        scope.isEmpty     = results.length === 0;
        scope.results     = results;
        scope.showList    = true;
        scope.isSearching = false;
      }

      function geocodedWithPlaceId (results) {
        var result = results[0];

        if (result) {
          scope.query    = result.formatted_address;
          scope.result   = result;

          scope.showList = false;
        }
      }

      function selectItem (index) {
        $timeout(function () {
          scope.index    = index;
          scope.result   = scope.results[index];
          scope.query    = scope.result.formatted_address;

          scope.showList = false;
        }, 0);
      }

      function displayList () {
        return scope.query.length >= scope.minLength && scope.showList;
      }

      function handleArrowKeys(key) {
        var index         = scope.index;
        var resultsLength = scope.results.length;

        var arrowUp   = key === 38;
        var arrowDown = key === 40;

        if (arrowUp && (index - 1 >= 0)) {
          index--;
        }

        if (arrowDown && (index + 1 < resultsLength)) {
          index++;
        }

        scope.$apply(function () {
          scope.index = index;
        });

        if (arrowUp   && scope.results.length) fixArrowUpScroll();
        if (arrowDown && scope.results.length) fixArrowDownScroll();
      }

      function fixArrowUpScroll() {
        var rowTop = dropdownRowTop();
        var height = dropdownRowOffsetHeight(getCurrentRow());

        if (rowTop < height) {
          dropdownScrollTo(rowTop - height);
        }
      }

      function fixArrowDownScroll () {
        var row = getCurrentRow();

        if (getDropdownHeight() < row.getBoundingClientRect().bottom) {
          dropdownScrollTo(dropdownRowOffsetHeight(row));
        }
      }

      function getCurrentRow () {
        return $el.querySelector(".ng-geocoder__list__item--focus");
      }

      function dropdownRowTop () {
        return getCurrentRow().getBoundingClientRect().top - (dropdown.getBoundingClientRect().top + parseInt(getComputedStyle(dropdown).paddingTop, 10));
      }

      function dropdownScrollTo (offset) {
        dropdown.scrollTop = dropdown.scrollTop + offset;
      }

      function getDropdownHeight () {
        return dropdown.getBoundingClientRect().top + parseInt(getComputedStyle(dropdown).maxHeight, 10);
      }

      function dropdownRowOffsetHeight (row) {
        var css = getComputedStyle(row);

        return row.offsetHeight + parseInt(css.marginTop, 10) + parseInt(css.marginBottom, 10);
      }
    }

    function geocoderTemplate (element, attributes) {
      return attributes.templateUrl || DEFAULT_TEMPLATE_URL
    }
  }
})();
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------------------------------
// OpenSeaMap Water Depth - Web frontend for depth data handling.
//
// Written in 2012 by Dominik Fässler dfa@bezono.org
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
// -------------------------------------------------------------------------------------------------

OSeaM.views.MapTracks = OSeaM.View.extend({
    render: function() {
        var template = OSeaM.loadTemplate('maptracks');
        var content = $(template());
        OSeaM.frontend.translate(content);
        this.$el.html(content);
        this.initOpenLayers();
        return this;
    },
    mapEventMove: function (view) {
        var fn = function(data) {
//            this.attributionControl.updateAttribution();
            this.layerBase.attribution = 'Data CC-By-SA by OpenStreetMap',
            this.layerTrackPoints10.attribution = data;
            this.layerTrackPoints.attribution = data;
            this.attributionControl.draw();
//            this.attributionControl = new OpenLayers.Control.Attribution();
            this.attributionControl.updateAttribution();
        };
        if(this.map != null) {
        var bounds = this.map.getExtent().toArray();
        var b = this.y2lat(bounds[1]).toFixed(5);
        var t = this.y2lat(bounds[3]).toFixed(5);
        var l = this.x2lon(bounds[0]).toFixed(5);
        var r = this.x2lon(bounds[2]).toFixed(5);

        jQuery.ajax({
            type: 'GET',
            url: OSeaM.apiUrl + 'license?lat1=' + b + '&lon1=' + l + '&lat2=' + t + '&lon2=' + r  ,
            dataType: 'text',
            success: jQuery.proxy(fn, this)
        });

        }

    },
    initOpenLayers: function() {

        this.projectionWGS84    = new OpenLayers.Projection('EPSG:4326');
        this.projectionMercator = new OpenLayers.Projection('EPSG:900913');
        this.maxExtent          = new OpenLayers.Bounds(-180, -89, 180, 89).transform(
                                          this.projectionWGS84,
                                          this.projectionMercator
                                      );

        this.map = new OpenLayers.Map(this.$el.find('.oseam-map-tracks')[0], {
            projection: this.projectionMercator,
            displayProjection: this.projectionWGS84,
            maxExtent: this.maxExtent,
            numZoomLevels: 22,
            maxResolution: 156543.0399,
//        	events: {
//        		moveend     : this.mapEventMove(this),
//        		zoomend     : this.mapEventMove(this)
//        	},
            units: 'meters'
        });

        this.layerBase = new OpenLayers.Layer.XYZ('OpenStreetMap',
            'http://osm1.wtnet.de/tiles/base/${z}/${x}/${y}.png', {
                resolutions: [
                    156543.03390625, 78271.516953125, 39135.7584765625,
                    19567.87923828125, 9783.939619140625, 4891.9698095703125,
                    2445.9849047851562, 1222.9924523925781, 611.4962261962891,
                    305.74811309814453, 152.87405654907226, 76.43702827453613,
                    38.218514137268066, 19.109257068634033, 9.554628534317017,
                    4.777314267158508, 2.388657133579254, 1.194328566789627,
                    0.5971642833948135, 0.25, 0.1, 0.05
                ],
                serverResolutions: [
                    156543.03390625, 78271.516953125, 39135.7584765625,
                    19567.87923828125, 9783.939619140625, 4891.9698095703125,
                    2445.9849047851562, 1222.9924523925781, 611.4962261962891,
                    305.74811309814453, 152.87405654907226, 76.43702827453613,
                    38.218514137268066, 19.109257068634033, 9.554628534317017,
                    4.777314267158508, 2.388657133579254, 1.194328566789627,
                    0.5971642833948135
                ],
                transitionEffect: 'resize',
                sphericalMercator: true
            }
        );
        this.layerTrackPoints = new OpenLayers.Layer.WMS('100m',
            'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                layers: 'trackpoints_cor1_test_dbs,trackpoints_cor1_test,test_zoom_10_cor_1_points,test_zoom_9_cor_1_points,test_zoom_8_cor_1_points,test_zoom_7_cor_1_points,test_zoom_6_cor_1_points,test_zoom_5_cor_1_points,test_zoom_4_cor_1_points,test_zoom_3_cor_1_points,test_zoom_2_cor_1_points',
                numZoomLevels: 22,
                projection: this.projectionMercator,
                type: 'png',
                transparent: true
            },{
                isBaseLayer: false,
                tileSize: new OpenLayers.Size(1024,1024)
            }
        );
        this.layerTrackPoints10 = new OpenLayers.Layer.WMS('10m',
                'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                    layers: 'trackpoints_cor1_test_dbs_10,trackpoints_cor1_test_10,test_zoom_10_cor_1_points_10,test_zoom_9_cor_1_points_10,test_zoom_8_cor_1_points_10,test_zoom_7_cor_1_points_10,test_zoom_6_cor_1_points_10,test_zoom_5_cor_1_points_10,test_zoom_4_cor_1_points_10,test_zoom_3_cor_1_points_10,test_zoom_2_cor_1_points_10',
                    numZoomLevels: 22,
                    projection: this.projectionMercator,
                    type: 'png',
                    transparent: true
                },{
                    isBaseLayer: false,
                    tileSize: new OpenLayers.Size(1024,1024),
                    visibility : false
                }
            );
        this.layerTrackPoints_filter1 = new OpenLayers.Layer.WMS('100m Filter 1',
                'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                    layers: 'trackpoints_filter1_0,trackpoints_filter1_1',
                    numZoomLevels: 22,
                    projection: this.projectionMercator,
                    type: 'png',
                    transparent: true
                },{
                    isBaseLayer: false,
                    tileSize: new OpenLayers.Size(1024,1024),
                visibility : false
                }
            );
//            this.layerTrackPoints10_filter1 = new OpenLayers.Layer.WMS('10m Filter 1',
//                    'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
//                        layers: 'trackpoints_cor1_test_dbs_10,trackpoints_cor1_test_10,test_zoom_10_cor_1_points_10,test_zoom_9_cor_1_points_10,test_zoom_8_cor_1_points_10,test_zoom_7_cor_1_points_10,test_zoom_6_cor_1_points_10,test_zoom_5_cor_1_points_10,test_zoom_4_cor_1_points_10,test_zoom_3_cor_1_points_10,test_zoom_2_cor_1_points_10',
//                        numZoomLevels: 22,
//                        projection: this.projectionMercator,
//                        type: 'png',
//                        transparent: true
//                    },{
//                        isBaseLayer: false,
//                        tileSize: new OpenLayers.Size(1024,1024),
//                        visibility : false
//                    }
//                );
            this.layerTrackPoints_filter2 = new OpenLayers.Layer.WMS('100m Filter 2',
                    'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                        layers: 'trackpoints_filter2_0,trackpoints_filter2_1',
                        numZoomLevels: 22,
                        projection: this.projectionMercator,
                        type: 'png',
                        transparent: true
                    },{
                        isBaseLayer: false,
                        tileSize: new OpenLayers.Size(1024,1024),
                    	visibility : false
                    }
                );
//             this.layerTrackPoints10_filter2 = new OpenLayers.Layer.WMS('10m Filter 2',
//                        'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
//                            layers: 'trackpoints_cor1_test_dbs_10,trackpoints_cor1_test_10,test_zoom_10_cor_1_points_10,test_zoom_9_cor_1_points_10,test_zoom_8_cor_1_points_10,test_zoom_7_cor_1_points_10,test_zoom_6_cor_1_points_10,test_zoom_5_cor_1_points_10,test_zoom_4_cor_1_points_10,test_zoom_3_cor_1_points_10,test_zoom_2_cor_1_points_10',
//                            numZoomLevels: 22,
//                            projection: this.projectionMercator,
//                            type: 'png',
//                            transparent: true
//                        },{
//                            isBaseLayer: false,
//                            tileSize: new OpenLayers.Size(1024,1024),
//                            visibility : false
//                        }
//                    );
         this.triangulation = new OpenLayers.Layer.WMS("Triangulation",
                    "http://osm.franken.de/cgi-bin/mapserv.fcgi?", {
        	 			layers: ['triangulation'],
        	 			projection: new OpenLayers.Projection("EPSG:900913"),
        	 			type: 'png',
        	 			transparent: true
        	 		}, {
        	 			visibility: false,
        	 			isBaseLayer: false,
        	 			tileSize: new OpenLayers.Size(1024,1024)
        	 		});

         this.msl2lat = new OpenLayers.Layer.WMS("Mean Sea Level to LAT Difference",
                 "http://osm.franken.de/cgi-bin/mapserv.fcgi", {
        	 			layers: "lat",
        	 			projection: new OpenLayers.Projection("EPSG:900913"),
        	 			type: 'png',
        	 			transparent: true
        	 	  },{
        	 		  visibility: false,
        	 		  isBaseLayer: false,
        	 		  tileSize: new OpenLayers.Size(1024,1024)
        	 	  });
        this.layerContours = new OpenLayers.Layer.WMS("Contours",
                'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
            layers: ['contour','contour2'],
            numZoomLevels: 22,
            projection: this.projectionMercator,
            type: 'png',

            transparent: true
        },{
            isBaseLayer: false,
            tileSize: new OpenLayers.Size(1024,1024),
            visibility : false
        }
    );

        this.map.addLayers([
            this.layerBase,
            this.triangulation,
            this.layerTrackPoints,
            this.layerTrackPoints10,
            this.layerTrackPoints_filter1,
            this.layerTrackPoints_filter2,
            this.layerContours,
            this.msl2lat
        ]);
        this.attributionControl = new OpenLayers.Control.Attribution();
        this.map.addControls([
            this.attributionControl,
            new OpenLayers.Control.KeyboardDefaults(),
            new OpenLayers.Control.LayerSwitcher()
        ]);
        this.map.setCenter(new OpenLayers.LonLat(0.0, 40.0).transform(
            this.projectionWGS84,
            this.projectionMercator
          ), 3
        );
        this.map.events.register( 'moveend', this, this.mapEventMove);

        this.mapEventMove(this);
    },
    plusfacteur : function (a) {
        return a * (20037508.34 / 180);
    },

    moinsfacteur: function (a) {
        return a / (20037508.34 / 180);
    },

    y2lat: function (a) {
        return 180/Math.PI * (2 * Math.atan(Math.exp(this.moinsfacteur(a)*Math.PI/180)) - Math.PI/2);
    },

    lat2y: function (a) {
        return this.plusfacteur(180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)));
    },

    x2lon: function (a) {
        return this.moinsfacteur(a);
    },

    lon2x: function (a) {
        return this.plusfacteur(a);
    }
});
<commit_msg>B: Use corrcect license URL<commit_after>// -------------------------------------------------------------------------------------------------
// OpenSeaMap Water Depth - Web frontend for depth data handling.
//
// Written in 2012 by Dominik Fässler dfa@bezono.org
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
// -------------------------------------------------------------------------------------------------

OSeaM.views.MapTracks = OSeaM.View.extend({
    render: function() {
        var template = OSeaM.loadTemplate('maptracks');
        var content = $(template());
        OSeaM.frontend.translate(content);
        this.$el.html(content);
        this.initOpenLayers();
        return this;
    },
    mapEventMove: function (view) {
        var fn = function(data) {
//            this.attributionControl.updateAttribution();
            this.layerBase.attribution = 'Data CC-By-SA by OpenStreetMap',
            this.layerTrackPoints10.attribution = data;
            this.layerTrackPoints.attribution = data;
            this.attributionControl.draw();
//            this.attributionControl = new OpenLayers.Control.Attribution();
            this.attributionControl.updateAttribution();
        };
        if(this.map != null) {
        var bounds = this.map.getExtent().toArray();
        var b = this.y2lat(bounds[1]).toFixed(5);
        var t = this.y2lat(bounds[3]).toFixed(5);
        var l = this.x2lon(bounds[0]).toFixed(5);
        var r = this.x2lon(bounds[2]).toFixed(5);

        jQuery.ajax({
            type: 'GET',
            url: OSeaM.apiUrl + 'license/bbox?lat1=' + b + '&lon1=' + l + '&lat2=' + t + '&lon2=' + r  ,
            dataType: 'text',
            success: jQuery.proxy(fn, this)
        });

        }

    },
    initOpenLayers: function() {

        this.projectionWGS84    = new OpenLayers.Projection('EPSG:4326');
        this.projectionMercator = new OpenLayers.Projection('EPSG:900913');
        this.maxExtent          = new OpenLayers.Bounds(-180, -89, 180, 89).transform(
                                          this.projectionWGS84,
                                          this.projectionMercator
                                      );

        this.map = new OpenLayers.Map(this.$el.find('.oseam-map-tracks')[0], {
            projection: this.projectionMercator,
            displayProjection: this.projectionWGS84,
            maxExtent: this.maxExtent,
            numZoomLevels: 22,
            maxResolution: 156543.0399,
//        	events: {
//        		moveend     : this.mapEventMove(this),
//        		zoomend     : this.mapEventMove(this)
//        	},
            units: 'meters'
        });

        this.layerBase = new OpenLayers.Layer.XYZ('OpenStreetMap',
            'http://osm1.wtnet.de/tiles/base/${z}/${x}/${y}.png', {
                resolutions: [
                    156543.03390625, 78271.516953125, 39135.7584765625,
                    19567.87923828125, 9783.939619140625, 4891.9698095703125,
                    2445.9849047851562, 1222.9924523925781, 611.4962261962891,
                    305.74811309814453, 152.87405654907226, 76.43702827453613,
                    38.218514137268066, 19.109257068634033, 9.554628534317017,
                    4.777314267158508, 2.388657133579254, 1.194328566789627,
                    0.5971642833948135, 0.25, 0.1, 0.05
                ],
                serverResolutions: [
                    156543.03390625, 78271.516953125, 39135.7584765625,
                    19567.87923828125, 9783.939619140625, 4891.9698095703125,
                    2445.9849047851562, 1222.9924523925781, 611.4962261962891,
                    305.74811309814453, 152.87405654907226, 76.43702827453613,
                    38.218514137268066, 19.109257068634033, 9.554628534317017,
                    4.777314267158508, 2.388657133579254, 1.194328566789627,
                    0.5971642833948135
                ],
                transitionEffect: 'resize',
                sphericalMercator: true
            }
        );
        this.layerTrackPoints = new OpenLayers.Layer.WMS('100m',
            'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                layers: 'trackpoints_cor1_test_dbs,trackpoints_cor1_test,test_zoom_10_cor_1_points,test_zoom_9_cor_1_points,test_zoom_8_cor_1_points,test_zoom_7_cor_1_points,test_zoom_6_cor_1_points,test_zoom_5_cor_1_points,test_zoom_4_cor_1_points,test_zoom_3_cor_1_points,test_zoom_2_cor_1_points',
                numZoomLevels: 22,
                projection: this.projectionMercator,
                type: 'png',
                transparent: true
            },{
                isBaseLayer: false,
                tileSize: new OpenLayers.Size(1024,1024)
            }
        );
        this.layerTrackPoints10 = new OpenLayers.Layer.WMS('10m',
                'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                    layers: 'trackpoints_cor1_test_dbs_10,trackpoints_cor1_test_10,test_zoom_10_cor_1_points_10,test_zoom_9_cor_1_points_10,test_zoom_8_cor_1_points_10,test_zoom_7_cor_1_points_10,test_zoom_6_cor_1_points_10,test_zoom_5_cor_1_points_10,test_zoom_4_cor_1_points_10,test_zoom_3_cor_1_points_10,test_zoom_2_cor_1_points_10',
                    numZoomLevels: 22,
                    projection: this.projectionMercator,
                    type: 'png',
                    transparent: true
                },{
                    isBaseLayer: false,
                    tileSize: new OpenLayers.Size(1024,1024),
                    visibility : false
                }
            );
        this.layerTrackPoints_filter1 = new OpenLayers.Layer.WMS('100m Filter 1',
                'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                    layers: 'trackpoints_filter1_0,trackpoints_filter1_1',
                    numZoomLevels: 22,
                    projection: this.projectionMercator,
                    type: 'png',
                    transparent: true
                },{
                    isBaseLayer: false,
                    tileSize: new OpenLayers.Size(1024,1024),
                visibility : false
                }
            );
//            this.layerTrackPoints10_filter1 = new OpenLayers.Layer.WMS('10m Filter 1',
//                    'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
//                        layers: 'trackpoints_cor1_test_dbs_10,trackpoints_cor1_test_10,test_zoom_10_cor_1_points_10,test_zoom_9_cor_1_points_10,test_zoom_8_cor_1_points_10,test_zoom_7_cor_1_points_10,test_zoom_6_cor_1_points_10,test_zoom_5_cor_1_points_10,test_zoom_4_cor_1_points_10,test_zoom_3_cor_1_points_10,test_zoom_2_cor_1_points_10',
//                        numZoomLevels: 22,
//                        projection: this.projectionMercator,
//                        type: 'png',
//                        transparent: true
//                    },{
//                        isBaseLayer: false,
//                        tileSize: new OpenLayers.Size(1024,1024),
//                        visibility : false
//                    }
//                );
            this.layerTrackPoints_filter2 = new OpenLayers.Layer.WMS('100m Filter 2',
                    'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
                        layers: 'trackpoints_filter2_0,trackpoints_filter2_1',
                        numZoomLevels: 22,
                        projection: this.projectionMercator,
                        type: 'png',
                        transparent: true
                    },{
                        isBaseLayer: false,
                        tileSize: new OpenLayers.Size(1024,1024),
                    	visibility : false
                    }
                );
//             this.layerTrackPoints10_filter2 = new OpenLayers.Layer.WMS('10m Filter 2',
//                        'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
//                            layers: 'trackpoints_cor1_test_dbs_10,trackpoints_cor1_test_10,test_zoom_10_cor_1_points_10,test_zoom_9_cor_1_points_10,test_zoom_8_cor_1_points_10,test_zoom_7_cor_1_points_10,test_zoom_6_cor_1_points_10,test_zoom_5_cor_1_points_10,test_zoom_4_cor_1_points_10,test_zoom_3_cor_1_points_10,test_zoom_2_cor_1_points_10',
//                            numZoomLevels: 22,
//                            projection: this.projectionMercator,
//                            type: 'png',
//                            transparent: true
//                        },{
//                            isBaseLayer: false,
//                            tileSize: new OpenLayers.Size(1024,1024),
//                            visibility : false
//                        }
//                    );
         this.triangulation = new OpenLayers.Layer.WMS("Triangulation",
                    "http://osm.franken.de/cgi-bin/mapserv.fcgi?", {
        	 			layers: ['triangulation'],
        	 			projection: new OpenLayers.Projection("EPSG:900913"),
        	 			type: 'png',
        	 			transparent: true
        	 		}, {
        	 			visibility: false,
        	 			isBaseLayer: false,
        	 			tileSize: new OpenLayers.Size(1024,1024)
        	 		});

         this.msl2lat = new OpenLayers.Layer.WMS("Mean Sea Level to LAT Difference",
                 "http://osm.franken.de/cgi-bin/mapserv.fcgi", {
        	 			layers: "lat",
        	 			projection: new OpenLayers.Projection("EPSG:900913"),
        	 			type: 'png',
        	 			transparent: true
        	 	  },{
        	 		  visibility: false,
        	 		  isBaseLayer: false,
        	 		  tileSize: new OpenLayers.Size(1024,1024)
        	 	  });
        this.layerContours = new OpenLayers.Layer.WMS("Contours",
                'http:///osm.franken.de/cgi-bin/mapserv.fcgi?', {
            layers: ['contour','contour2'],
            numZoomLevels: 22,
            projection: this.projectionMercator,
            type: 'png',

            transparent: true
        },{
            isBaseLayer: false,
            tileSize: new OpenLayers.Size(1024,1024),
            visibility : false
        }
    );

        this.map.addLayers([
            this.layerBase,
            this.triangulation,
            this.layerTrackPoints,
            this.layerTrackPoints10,
            this.layerTrackPoints_filter1,
            this.layerTrackPoints_filter2,
            this.layerContours,
            this.msl2lat
        ]);
        this.attributionControl = new OpenLayers.Control.Attribution();
        this.map.addControls([
            this.attributionControl,
            new OpenLayers.Control.KeyboardDefaults(),
            new OpenLayers.Control.LayerSwitcher()
        ]);
        this.map.setCenter(new OpenLayers.LonLat(0.0, 40.0).transform(
            this.projectionWGS84,
            this.projectionMercator
          ), 3
        );
        this.map.events.register( 'moveend', this, this.mapEventMove);

        this.mapEventMove(this);
    },
    plusfacteur : function (a) {
        return a * (20037508.34 / 180);
    },

    moinsfacteur: function (a) {
        return a / (20037508.34 / 180);
    },

    y2lat: function (a) {
        return 180/Math.PI * (2 * Math.atan(Math.exp(this.moinsfacteur(a)*Math.PI/180)) - Math.PI/2);
    },

    lat2y: function (a) {
        return this.plusfacteur(180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)));
    },

    x2lon: function (a) {
        return this.moinsfacteur(a);
    },

    lon2x: function (a) {
        return this.plusfacteur(a);
    }
});
<|endoftext|>


<commit_before>define([
  'angular',
  'lodash',
  'kbn',
  './queryCtrl',
],
function (angular, _, kbn) {
  'use strict';

  var module = angular.module('grafana.services');
  var tagList = null;

  module.factory('KairosDBDatasource', function($q, $http) {

    function KairosDBDatasource(datasource) {
      this.type = datasource.type;
      this.editorSrc = 'plugins/datasources/kairosdb/kairosdb.editor.html';
      this.url = datasource.url;
      this.name = datasource.name;
      this.supportMetrics = true;
      this.grafanaDB = datasource.grafanaDB;
    }

    // Called once per panel (graph)
    KairosDBDatasource.prototype.query = function(options) {
      var start = options.range.from;
      var end = options.range.to;

      var queries = _.compact(_.map(options.targets, _.partial(convertTargetToQuery, options)));
      var plotParams = _.compact(_.map(options.targets, function(target) {
        var alias = target.alias;
        if (typeof target.alias == 'undefined' || target.alias == "")
          alias = target.metric;
        return !target.hide
            ?  {alias: alias,
                exouter: target.exOuter}
            : null;
      }));
      var handleKairosDBQueryResponseAlias = _.partial(handleKairosDBQueryResponse, plotParams);
      // No valid targets, return the empty result to save a round trip.
      if (_.isEmpty(queries)) {
        var d = $q.defer();
        d.resolve({ data: [] });
        return d.promise;
      }
      return this.performTimeSeriesQuery(queries, start, end).then(handleKairosDBQueryResponseAlias,handleQueryError);
    };

    ///////////////////////////////////////////////////////////////////////
    /// Query methods
    ///////////////////////////////////////////////////////////////////////

    KairosDBDatasource.prototype.performTimeSeriesQuery = function(queries, start, end) {
      var reqBody = {
        metrics: queries
      };
      reqBody.cache_time=0;
      convertToKairosTime(start,reqBody,'start');
      convertToKairosTime(end,reqBody,'end');
      var options = {
        method: 'POST',
        url: '/api/v1/datapoints/query',
        data: reqBody
      };

      options.url = this.url + options.url;
      return $http(options);
    };

    /**
     * Gets the list of metrics
     * @returns {*|Promise}
     */
    KairosDBDatasource.prototype.performMetricSuggestQuery = function() {
      var options = {
        url : this.url + '/api/v1/metricnames',
        method : 'GET'
      };
      return $http(options).then(function(results) {
        if (!results.data) {
          return [];
        }
        return results.data.results;
      });

    };

    KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname,range,type,keyValue) {
      if (tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) &&
        (range.to === tagList.range.to)) {
        return getTagListFromResponse(tagList.results,type,keyValue);
      }
      tagList = {
        metricName:metricname,
        range:range
      };
      var body = {
        metrics : [{name : metricname}]
      };
      convertToKairosTime(range.from,body,'start');
      convertToKairosTime(range.to,body,'end');
      var options = {
        url : this.url + '/api/v1/datapoints/query/tags',
        method : 'POST',
        data : body
      };
      return $http(options).then(function(results) {
        tagList.results = results;
        return getTagListFromResponse(results,type,keyValue);
      });

    };

    /////////////////////////////////////////////////////////////////////////
    /// Formatting methods
    ////////////////////////////////////////////////////////////////////////

    function getTagListFromResponse(results,type,keyValue) {
      if (!results.data) {
        return [];
      }
      if (type==="key") {
        return _.keys(results.data.queries[0].results[0].tags);
      }
      else if (type==="value" && _.has(results.data.queries[0].results[0].tags,keyValue)) {
        return results.data.queries[0].results[0].tags[keyValue];
      }
      return [];
    }

    /**
     * Requires a verion of KairosDB with every CORS defects fixed
     * @param results
     * @returns {*}
     */
    function handleQueryError(results) {
      if (results.data.errors && !_.isEmpty(results.data.errors)) {
        var errors = {
          message: results.data.errors[0]
        };
        return $q.reject(errors);
      }
      else {
        return $q.reject(results);
      }
    }

    function handleKairosDBQueryResponse(plotParams, results) {
      var output = [];
      var index = 0;
      _.each(results.data.queries, function (series) {
        var sample_size = series.sample_size;
        console.log("sample_size:" + sample_size + " samples");

        _.each(series.results, function (result) {

          //var target = result.name;
          var target = plotParams[index].alias;
          var details = " ( ";
          _.each(result.group_by,function(element) {
            if (element.name==="tag") {
              _.each(element.group,function(value, key) {
                details+= key+"="+value+" ";
              });
            }
            else if (element.name==="value") {
              details+= 'value_group='+element.group.group_number+" ";
            }
            else if (element.name==="time") {
              details+= 'time_group='+element.group.group_number+" ";
            }
          });
          details+= ") ";
          if (details != " ( ) ")
            target += details;
          var datapoints = [];

          for (var i = 0; i < result.values.length; i++) {
            var t = Math.floor(result.values[i][0]);
            var v = result.values[i][1];
            datapoints[i] = [v, t];
          }
          if (plotParams[index].exouter)
            datapoints = PeakFilter(datapoints, 10);
          output.push({ target: target, datapoints: datapoints });
        });
        index ++;
      });
      var output2 = { data: _.flatten(output) };

      return output2;
    }

    function convertTargetToQuery(options,target) {
      if (!target.metric || target.hide) {
        return null;
      }

      var query = {
        name: target.metric
      };

      query.aggregators = [];
      if (target.downsampling!=='(NONE)') {
        query.aggregators.push({
          name: target.downsampling,
          align_sampling: true,
          align_start_time: true,
          sampling: KairosDBDatasource.prototype.convertToKairosInterval(target.sampling || options.interval)
        });
      }
      if (target.horizontalAggregators) {
        _.each(target.horizontalAggregators,function(chosenAggregator) {
          var returnedAggregator = {
            name:chosenAggregator.name
          };
          if (chosenAggregator.sampling_rate) {
            returnedAggregator.sampling = KairosDBDatasource.prototype.convertToKairosInterval(chosenAggregator.sampling_rate);
            returnedAggregator.align_sampling = true;
            returnedAggregator.align_start_time =true;
          }
          if (chosenAggregator.unit) {
            returnedAggregator.unit = chosenAggregator.unit+'s';
          }
          if (chosenAggregator.factor && chosenAggregator.name==='div') {
            returnedAggregator.divisor = chosenAggregator.factor;
          }
          else if (chosenAggregator.factor && chosenAggregator.name==='scale') {
            returnedAggregator.factor  = chosenAggregator.factor;
          }
          if (chosenAggregator.percentile) {
            returnedAggregator.percentile = chosenAggregator.percentile;
          }
          query.aggregators.push(returnedAggregator);
        });
      }
      if (_.isEmpty(query.aggregators)) {
        delete query.aggregators;
      }

      if (target.tags) {
        query.tags = angular.copy(target.tags);
      }

      if (target.groupByTags || target.nonTagGroupBys) {
        query.group_by = [];
        if (target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});}
        if (target.nonTagGroupBys) {
          _.each(target.nonTagGroupBys,function(rawGroupBy) {
            var formattedGroupBy = angular.copy(rawGroupBy);
            if (formattedGroupBy.name==='time') {
              formattedGroupBy.range_size=KairosDBDatasource.prototype.convertToKairosInterval(formattedGroupBy.range_size);
            }
            query.group_by.push(formattedGroupBy);
          });
        }
      }
      return query;
    }

    ///////////////////////////////////////////////////////////////////////
    /// Time conversion functions specifics to KairosDB
    //////////////////////////////////////////////////////////////////////

    KairosDBDatasource.prototype.convertToKairosInterval = function(intervalString) {
      var interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/;
      var interval_regex_ms = /(\d+(?:\.\d+)?)(ms)/;
      var matches = intervalString.match(interval_regex_ms);
      if (!matches) {
        matches = intervalString.match(interval_regex);
      }
      if (!matches) {
        throw new Error('Invalid interval string, expecting a number followed by one of "y M w d h m s ms"');
      }

      var value = matches[1];
      var unit = matches[2];
      if (value%1!==0) {
        if (unit==='ms') {throw new Error('Invalid interval value, cannot be smaller than the millisecond');}
        value = Math.round(kbn.intervals_in_seconds[unit]*value*1000);
        unit = 'ms';

      }
      switch (unit) {
        case 'ms':
          unit = 'milliseconds';
          break;
        case 's':
          unit = 'seconds';
          break;
        case 'm':
          unit = 'minutes';
          break;
        case 'h':
          unit = 'hours';
          break;
        case 'd':
          unit = 'days';
          break;
        case 'w':
          unit = 'weeks';
          break;
        case 'M':
          unit = 'months';
          break;
        case 'y':
          unit = 'years';
          break;
        default:
          console.log("Unknown interval ", intervalString);
          break;
      }

      return {
        "value": value,
        "unit": unit
      };

    };

    function convertToKairosTime(date, response_obj, start_stop_name) {
      var name;
      if (_.isString(date)) {
        if (date === 'now') {
          return;
        }
        else if (date.indexOf('now-') >= 0) {

          name = start_stop_name + "_relative";

          date = date.substring(4);
          var re_date = /(\d+)\s*(\D+)/;
          var result = re_date.exec(date);
          if (result) {
            var value = result[1];
            var unit = result[2];
            switch (unit) {
              case 'ms':
                unit = 'milliseconds';
                break;
              case 's':
                unit = 'seconds';
                break;
              case 'm':
                unit = 'minutes';
                break;
              case 'h':
                unit = 'hours';
                break;
              case 'd':
                unit = 'days';
                break;
              case 'w':
                unit = 'weeks';
                break;
              case 'M':
                unit = 'months';
                break;
              case 'y':
                unit = 'years';
                break;
              default:
                console.log("Unknown date ", date);
                break;
            }
            response_obj[name] = {
              "value": value,
              "unit": unit
            };
            return;
          }
          console.log("Unparseable date", date);
          return;
        }
        date = kbn.parseDate(date);
      }

      if (_.isDate(date)) {
        name = start_stop_name + "_absolute";
        response_obj[name] = date.getTime();
        return;
      }

      console.log("Date is neither string nor date");
    }

    function PeakFilter(dataIn, limit) {
      var datapoints = dataIn;
      var arrLength = datapoints.length;
      if (arrLength <= 3)
        return datapoints;
      var LastIndx = arrLength - 1;

      // Check first point
      var prvDelta = Math.abs((datapoints[1][0] - datapoints[0][0]) / datapoints[0][0]);
      var nxtDelta = Math.abs((datapoints[1][0] - datapoints[2][0]) / datapoints[2][0]);
      if (prvDelta >= limit && nxtDelta < limit)
        datapoints[0][0] = datapoints[1][0];

      // Check last point
      prvDelta = Math.abs((datapoints[LastIndx - 1][0] - datapoints[LastIndx - 2][0]) / datapoints[LastIndx - 2][0]);
      nxtDelta = Math.abs((datapoints[LastIndx - 1][0] - datapoints[LastIndx][0]) / datapoints[LastIndx][0]);
      if (prvDelta >= limit && nxtDelta < limit)
        datapoints[LastIndx][0] = datapoints[LastIndx - 1][0];

      for (var i = 1; i < arrLength - 1; i++) {
        prvDelta = Math.abs((datapoints[i][0] - datapoints[i - 1][0]) / datapoints[i - 1][0]);
        nxtDelta = Math.abs((datapoints[i][0] - datapoints[i + 1][0]) / datapoints[i + 1][0]);
        if (prvDelta >= limit && nxtDelta >= limit)
          datapoints[i][0] = (datapoints[i-1][0] + datapoints[i+1][0]) / 2;
      }

      return datapoints;
    }

    ////////////////////////////////////////////////////////////////////////
    return KairosDBDatasource;
  });

});
<commit_msg>Fix styles warned by jshint<commit_after>define([
  'angular',
  'lodash',
  'kbn',
  './queryCtrl',
],
function (angular, _, kbn) {
  'use strict';

  var module = angular.module('grafana.services');
  var tagList = null;

  module.factory('KairosDBDatasource', function($q, $http) {

    function KairosDBDatasource(datasource) {
      this.type = datasource.type;
      this.editorSrc = 'plugins/datasources/kairosdb/kairosdb.editor.html';
      this.url = datasource.url;
      this.name = datasource.name;
      this.supportMetrics = true;
      this.grafanaDB = datasource.grafanaDB;
    }

    // Called once per panel (graph)
    KairosDBDatasource.prototype.query = function(options) {
      var start = options.range.from;
      var end = options.range.to;

      var queries = _.compact(_.map(options.targets, _.partial(convertTargetToQuery, options)));
      var plotParams = _.compact(_.map(options.targets, function(target) {
        var alias = target.alias;
        if (typeof target.alias === 'undefined' || target.alias === "") {
          alias = target.metric;
        }
        return !target.hide
            ?  {alias: alias,
                exouter: target.exOuter}
            : null;
      }));
      var handleKairosDBQueryResponseAlias = _.partial(handleKairosDBQueryResponse, plotParams);
      // No valid targets, return the empty result to save a round trip.
      if (_.isEmpty(queries)) {
        var d = $q.defer();
        d.resolve({ data: [] });
        return d.promise;
      }
      return this.performTimeSeriesQuery(queries, start, end).then(handleKairosDBQueryResponseAlias,handleQueryError);
    };

    ///////////////////////////////////////////////////////////////////////
    /// Query methods
    ///////////////////////////////////////////////////////////////////////

    KairosDBDatasource.prototype.performTimeSeriesQuery = function(queries, start, end) {
      var reqBody = {
        metrics: queries
      };
      reqBody.cache_time=0;
      convertToKairosTime(start,reqBody,'start');
      convertToKairosTime(end,reqBody,'end');
      var options = {
        method: 'POST',
        url: '/api/v1/datapoints/query',
        data: reqBody
      };

      options.url = this.url + options.url;
      return $http(options);
    };

    /**
     * Gets the list of metrics
     * @returns {*|Promise}
     */
    KairosDBDatasource.prototype.performMetricSuggestQuery = function() {
      var options = {
        url : this.url + '/api/v1/metricnames',
        method : 'GET'
      };
      return $http(options).then(function(results) {
        if (!results.data) {
          return [];
        }
        return results.data.results;
      });

    };

    KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname,range,type,keyValue) {
      if (tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) &&
        (range.to === tagList.range.to)) {
        return getTagListFromResponse(tagList.results,type,keyValue);
      }
      tagList = {
        metricName:metricname,
        range:range
      };
      var body = {
        metrics : [{name : metricname}]
      };
      convertToKairosTime(range.from,body,'start');
      convertToKairosTime(range.to,body,'end');
      var options = {
        url : this.url + '/api/v1/datapoints/query/tags',
        method : 'POST',
        data : body
      };
      return $http(options).then(function(results) {
        tagList.results = results;
        return getTagListFromResponse(results,type,keyValue);
      });

    };

    /////////////////////////////////////////////////////////////////////////
    /// Formatting methods
    ////////////////////////////////////////////////////////////////////////

    function getTagListFromResponse(results,type,keyValue) {
      if (!results.data) {
        return [];
      }
      if (type==="key") {
        return _.keys(results.data.queries[0].results[0].tags);
      }
      else if (type==="value" && _.has(results.data.queries[0].results[0].tags,keyValue)) {
        return results.data.queries[0].results[0].tags[keyValue];
      }
      return [];
    }

    /**
     * Requires a verion of KairosDB with every CORS defects fixed
     * @param results
     * @returns {*}
     */
    function handleQueryError(results) {
      if (results.data.errors && !_.isEmpty(results.data.errors)) {
        var errors = {
          message: results.data.errors[0]
        };
        return $q.reject(errors);
      }
      else {
        return $q.reject(results);
      }
    }

    function handleKairosDBQueryResponse(plotParams, results) {
      var output = [];
      var index = 0;
      _.each(results.data.queries, function (series) {
        var sample_size = series.sample_size;
        console.log("sample_size:" + sample_size + " samples");

        _.each(series.results, function (result) {

          //var target = result.name;
          var target = plotParams[index].alias;
          var details = " ( ";
          _.each(result.group_by,function(element) {
            if (element.name==="tag") {
              _.each(element.group,function(value, key) {
                details+= key+"="+value+" ";
              });
            }
            else if (element.name==="value") {
              details+= 'value_group='+element.group.group_number+" ";
            }
            else if (element.name==="time") {
              details+= 'time_group='+element.group.group_number+" ";
            }
          });
          details+= ") ";
          if (details !== " ( ) ") {
            target += details;
          }
          var datapoints = [];

          for (var i = 0; i < result.values.length; i++) {
            var t = Math.floor(result.values[i][0]);
            var v = result.values[i][1];
            datapoints[i] = [v, t];
          }
          if (plotParams[index].exouter) {
            datapoints = new PeakFilter(datapoints, 10);
          }
          output.push({ target: target, datapoints: datapoints });
        });
        index ++;
      });
      var output2 = { data: _.flatten(output) };

      return output2;
    }

    function convertTargetToQuery(options,target) {
      if (!target.metric || target.hide) {
        return null;
      }

      var query = {
        name: target.metric
      };

      query.aggregators = [];
      if (target.downsampling!=='(NONE)') {
        query.aggregators.push({
          name: target.downsampling,
          align_sampling: true,
          align_start_time: true,
          sampling: KairosDBDatasource.prototype.convertToKairosInterval(target.sampling || options.interval)
        });
      }
      if (target.horizontalAggregators) {
        _.each(target.horizontalAggregators,function(chosenAggregator) {
          var returnedAggregator = {
            name:chosenAggregator.name
          };
          if (chosenAggregator.sampling_rate) {
            returnedAggregator.sampling = KairosDBDatasource.prototype.convertToKairosInterval(chosenAggregator.sampling_rate);
            returnedAggregator.align_sampling = true;
            returnedAggregator.align_start_time =true;
          }
          if (chosenAggregator.unit) {
            returnedAggregator.unit = chosenAggregator.unit+'s';
          }
          if (chosenAggregator.factor && chosenAggregator.name==='div') {
            returnedAggregator.divisor = chosenAggregator.factor;
          }
          else if (chosenAggregator.factor && chosenAggregator.name==='scale') {
            returnedAggregator.factor  = chosenAggregator.factor;
          }
          if (chosenAggregator.percentile) {
            returnedAggregator.percentile = chosenAggregator.percentile;
          }
          query.aggregators.push(returnedAggregator);
        });
      }
      if (_.isEmpty(query.aggregators)) {
        delete query.aggregators;
      }

      if (target.tags) {
        query.tags = angular.copy(target.tags);
      }

      if (target.groupByTags || target.nonTagGroupBys) {
        query.group_by = [];
        if (target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});}
        if (target.nonTagGroupBys) {
          _.each(target.nonTagGroupBys,function(rawGroupBy) {
            var formattedGroupBy = angular.copy(rawGroupBy);
            if (formattedGroupBy.name==='time') {
              formattedGroupBy.range_size=KairosDBDatasource.prototype.convertToKairosInterval(formattedGroupBy.range_size);
            }
            query.group_by.push(formattedGroupBy);
          });
        }
      }
      return query;
    }

    ///////////////////////////////////////////////////////////////////////
    /// Time conversion functions specifics to KairosDB
    //////////////////////////////////////////////////////////////////////

    KairosDBDatasource.prototype.convertToKairosInterval = function(intervalString) {
      var interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/;
      var interval_regex_ms = /(\d+(?:\.\d+)?)(ms)/;
      var matches = intervalString.match(interval_regex_ms);
      if (!matches) {
        matches = intervalString.match(interval_regex);
      }
      if (!matches) {
        throw new Error('Invalid interval string, expecting a number followed by one of "y M w d h m s ms"');
      }

      var value = matches[1];
      var unit = matches[2];
      if (value%1!==0) {
        if (unit==='ms') {throw new Error('Invalid interval value, cannot be smaller than the millisecond');}
        value = Math.round(kbn.intervals_in_seconds[unit]*value*1000);
        unit = 'ms';

      }
      switch (unit) {
        case 'ms':
          unit = 'milliseconds';
          break;
        case 's':
          unit = 'seconds';
          break;
        case 'm':
          unit = 'minutes';
          break;
        case 'h':
          unit = 'hours';
          break;
        case 'd':
          unit = 'days';
          break;
        case 'w':
          unit = 'weeks';
          break;
        case 'M':
          unit = 'months';
          break;
        case 'y':
          unit = 'years';
          break;
        default:
          console.log("Unknown interval ", intervalString);
          break;
      }

      return {
        "value": value,
        "unit": unit
      };

    };

    function convertToKairosTime(date, response_obj, start_stop_name) {
      var name;
      if (_.isString(date)) {
        if (date === 'now') {
          return;
        }
        else if (date.indexOf('now-') >= 0) {

          name = start_stop_name + "_relative";

          date = date.substring(4);
          var re_date = /(\d+)\s*(\D+)/;
          var result = re_date.exec(date);
          if (result) {
            var value = result[1];
            var unit = result[2];
            switch (unit) {
              case 'ms':
                unit = 'milliseconds';
                break;
              case 's':
                unit = 'seconds';
                break;
              case 'm':
                unit = 'minutes';
                break;
              case 'h':
                unit = 'hours';
                break;
              case 'd':
                unit = 'days';
                break;
              case 'w':
                unit = 'weeks';
                break;
              case 'M':
                unit = 'months';
                break;
              case 'y':
                unit = 'years';
                break;
              default:
                console.log("Unknown date ", date);
                break;
            }
            response_obj[name] = {
              "value": value,
              "unit": unit
            };
            return;
          }
          console.log("Unparseable date", date);
          return;
        }
        date = kbn.parseDate(date);
      }

      if (_.isDate(date)) {
        name = start_stop_name + "_absolute";
        response_obj[name] = date.getTime();
        return;
      }

      console.log("Date is neither string nor date");
    }

    function PeakFilter(dataIn, limit) {
      var datapoints = dataIn;
      var arrLength = datapoints.length;
      if (arrLength <= 3) {
        return datapoints;
      }
      var LastIndx = arrLength - 1;

      // Check first point
      var prvDelta = Math.abs((datapoints[1][0] - datapoints[0][0]) / datapoints[0][0]);
      var nxtDelta = Math.abs((datapoints[1][0] - datapoints[2][0]) / datapoints[2][0]);
      if (prvDelta >= limit && nxtDelta < limit) {
        datapoints[0][0] = datapoints[1][0];
      }

      // Check last point
      prvDelta = Math.abs((datapoints[LastIndx - 1][0] - datapoints[LastIndx - 2][0]) / datapoints[LastIndx - 2][0]);
      nxtDelta = Math.abs((datapoints[LastIndx - 1][0] - datapoints[LastIndx][0]) / datapoints[LastIndx][0]);
      if (prvDelta >= limit && nxtDelta < limit) {
        datapoints[LastIndx][0] = datapoints[LastIndx - 1][0];
      }

      for (var i = 1; i < arrLength - 1; i++) {
        prvDelta = Math.abs((datapoints[i][0] - datapoints[i - 1][0]) / datapoints[i - 1][0]);
        nxtDelta = Math.abs((datapoints[i][0] - datapoints[i + 1][0]) / datapoints[i + 1][0]);
        if (prvDelta >= limit && nxtDelta >= limit) {
          datapoints[i][0] = (datapoints[i-1][0] + datapoints[i+1][0]) / 2;
        }
      }

      return datapoints;
    }

    ////////////////////////////////////////////////////////////////////////
    return KairosDBDatasource;
  });

});
<|endoftext|>