<commit_before>/*
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

var core_basepath = null;

var init_debug = function( cloud_element )
{
  var debug_element = $( '#debug', cloud_element );
  var debug_button = $( '.dump a', cloud_element );

  var clipboard_element = $( '.clipboard', debug_element );
  var clipboard_button = $( 'a', clipboard_element );

  debug_button
    .die( 'click' )
    .live
    (
      'click',
      function( event )
      {
        debug_element.trigger( 'show' );
        return false;
      }
    );

  $( '.close', debug_element )
    .die( 'click' )
    .live
    (
      'click',
      function( event )
      {
        debug_element.trigger( 'hide' );
        return false;
      }
    );

  $( '.clipboard', debug_element )
    .die( 'click' )
    .live
    (
      'click',
      function( event )
      {
        return false;
      }
    );

  debug_element
    .die( 'show' )
    .live
    (
      'show',
      function( event )
      {
        debug_button.hide();
        debug_element.show();

        $.ajax
        (
          {
            url : core_basepath + '/zookeeper?wt=json&dump=true',
            dataType : 'text',
            context : debug_element,
            beforeSend : function( xhr, settings )
            {
              $( '.debug', debug_element )
                .html( 'Loading Dump ...' );

              ZeroClipboard.setMoviePath( 'img/ZeroClipboard.swf' );

              clipboard_client = new ZeroClipboard.Client();

              clipboard_client.addEventListener
              (
                'load',
                function( client )
                {
                }
              );

              clipboard_client.addEventListener
              (
                'complete',
                function( client, text )
                {
                  clipboard_element
                    .addClass( 'copied' );

                  clipboard_button
                    .data( 'text', clipboard_button.text() )
                    .text( clipboard_button.data( 'copied' ) );
                }
              );
            },
            success : function( response, text_status, xhr )
            {
              clipboard_client.glue
              (
                clipboard_element.get(0),
                clipboard_button.get(0)
              );

              clipboard_client.setText( response.replace( /\\/g, '\\\\' ) );

              $( '.debug', debug_element )
                .removeClass( 'loader' )
                .text( response );
            },
            error : function( xhr, text_status, error_thrown )
            {
            },
            complete : function( xhr, text_status )
            {
            }
          }
        );
      }
    )
    .die( 'hide' )
    .live
    (
      'hide',
      function( event )
      {
        $( '.debug', debug_element )
          .empty();

        clipboard_element
          .removeClass( 'copied' );

        clipboard_button
          .data( 'copied', clipboard_button.text() )
          .text( clipboard_button.data( 'text' ) );

        clipboard_client.destroy();

        debug_button.show();
        debug_element.hide();
      }
    );
};

var generate_graph = function( graph_element, graph_data )
{
  var w = 900,
      h = 300;

  var tree = d3.layout.tree()
      .size([h, w - 400]);

  var diagonal = d3.svg.diagonal()
      .projection(function(d) { return [d.y, d.x]; });

  var vis = d3.select("#canvas").append("svg")
      .attr("width", w)
      .attr("height", h)
    .append("g")
      .attr("transform", "translate(100, 0)");

  var nodes = tree.nodes(graph_data);

  var link = vis.selectAll("path.link")
      .data(tree.links(nodes))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", diagonal);

  var node = vis.selectAll("g.node")
      .data(nodes)
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 4.5);

  node.append("text")
      .attr("dx", function(d) { return d.children ? -8 : 8; })
      .attr("dy", 3)
      .attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
      .text(function(d) { return d.name; });

  /*
  var r = 860 / 2;

  var tree = d3.layout.tree()
      .size([360, r - 120])
      .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });

  var diagonal = d3.svg.diagonal.radial()
      .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });

  var vis = d3.select("#canvas").append("svg")
      .attr("width", r * 2)
      .attr("height", r * 2 - 150)
    .append("g")
      .attr("transform", "translate(" + r + "," + r + ")");

  var nodes = tree.nodes(graph_data);

  var link = vis.selectAll("path.link")
      .data(tree.links(nodes))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", diagonal);

  var node = vis.selectAll("g.node")
      .data(nodes)
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })

  node.append("circle")
      .attr("r", 4.5);

  node.append("text")
      .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
      .attr("dy", ".31em")
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
      .text(function(d) { return d.name; });
  //*/

};

var init_graph = function( graph_element )
{
  $.ajax
  (
    {
      url : core_basepath + '/zookeeper?wt=json&detail=true&path=%2Fclusterstate.json',
      dataType : 'json',
      context : graph_element,
      beforeSend : function( xhr, settings )
      {
        this
          .show();
      },
      success : function( response, text_status, xhr )
      {
        var state = null;
        eval( 'state = ' + response.znode.data + ';' );

        var collections = [];
        for( var c in state )
        {
          var shards = [];
          for( var s in state[c] )
          {
            var nodes = [];
            for( var n in state[c][s] )
            {
              var node = {
                id: state[c][s][n].node_name,
                name: state[c][s][n].base_url,
                data: {
                  type : 'node',
                  state : state[c][s][n].state,
                  leader : 'true' === state[c][s][n].leader
                }
              };
              nodes.push( node );
            }

            var shard = {
              id: s,
              name: s,
              data: {
                type : 'shard',
              },
              children: nodes
            };
            shards.push( shard );
          }

          var collection = {
            id: c,
            name: c,
            data: {
              type : 'collection',
            },
            children: shards
          };
          collections.push( collection );
        }

        var graph_data = collections.shift();
        generate_graph( graph_element, graph_data );
      },
      error : function( xhr, text_status, error_thrown)
      {
      },
      complete : function( xhr, text_status )
      {
      }
    }
  );

};

var init_tree = function( tree_element )
{
  $.ajax
  (
    {
      url : core_basepath + '/zookeeper?wt=json',
      dataType : 'json',
      context : tree_element,
      beforeSend : function( xhr, settings )
      {
        this
          .show();
      },
      success : function( response, text_status, xhr )
      {
        var self = this;

        $( '#tree', this )
          .jstree
          (
            {
              "plugins" : [ "json_data" ],
              "json_data" : {
                "data" : response.tree,
                "progressive_render" : true
              },
              "core" : {
                "animation" : 0
              }
            }
          )
          .jstree
          (
            'open_node',
            'li:first'
          );

        var tree_links = $( '#tree a', this );

        tree_links
          .die( 'click' )
          .live
          (
            'click',
            function( event )
            {
              $( 'a.active', $( this ).parents( '#tree' ) )
                .removeClass( 'active' );

              $( this )
                .addClass( 'active' );

              tree_element
                .addClass( 'show' );

              var file_content = $( '#file-content' );

              $( 'a.close', file_content )
                .die( 'click' )
                .live
                (
                  'click',
                  function( event )
                  {
                    $( '#tree a.active' )
                      .removeClass( 'active' );

                    tree_element
                      .removeClass( 'show' );

                    return false;
                  }
                );

              $.ajax
              (
                {
                  url : this.href,
                  dataType : 'json',
                  context : file_content,
                  beforeSend : function( xhr, settings )
                  {
                  },
                  success : function( response, text_status, xhr )
                  {
                    var props = [];
                    for( var key in response.znode.prop )
                    {
                      props.push
                      (
                        '

' + "\n" +
                          '
' + key.esc() + '
' + "\n" +
                          '
' + response.znode.prop[key].esc() + '
' + "\n" +
                        '

'
                      );
                    }

                    $( '#prop ul', this )
                      .empty()
                      .html( props.join( "\n" ) );

                    $( '#prop ul li:odd', this )
                      .addClass( 'odd' );

                    var data_element = $( '#data', this );

                    if( 0 !== parseInt( response.znode.prop.children_count ) )
                    {
                      data_element.hide();
                    }
                    else
                    {
                      var highlight = false;
                      var data = 'File "' + response.znode.path + '" has no Content';

                      if( response.znode.data )
                      {
                        var classes = '';
                        var path = response.znode.path.split( '.' );

                        if( 1 < path.length )
                        {
                          highlight = true;
                          classes = 'syntax language-' + path.pop().esc();
                        }

                        data = '
'
                             + response.znode.data.esc()
                             + '
';
                      }

                      data_element
                          .show()
                          .html( data );

                      if( highlight )
                      {
                        hljs.highlightBlock( data_element.get(0) );
                      }
                    }
                  },
                  error : function( xhr, text_status, error_thrown)
                  {
                  },
                  complete : function( xhr, text_status )
                  {
                  }
                }
              );

              return false;
            }
          );
      },
      error : function( xhr, text_status, error_thrown )
      {
        var message = 'Loading of ' + app.config.zookeeper_path + ' failed with "' + text_status + '" '
                    + '(' + error_thrown.message + ')';

        if( 200 !== xhr.status )
        {
          message = 'Loading of ' + app.config.zookeeper_path + ' failed with HTTP-Status ' + xhr.status + ' ';
        }

        this
          .html( '
' + message + '
' );
      },
      complete : function( xhr, text_status )
      {
      }
    }
  );
};

// #/~cloud
sammy.get
(
  /^#\/~(cloud)$/,
  function( context )
  {
    core_basepath = $( 'li[data-basepath]', app.menu_element ).attr( 'data-basepath' );
    var content_element = $( '#content' );

    $.get
    (
      'tpl/cloud.html',
      function( template )
      {
        content_element
          .html( template );

        var cloud_element = $( '#cloud', content_element );
        var navigation_element = $( '#navigation', content_element );

        init_debug( cloud_element );

        $( '.tree', navigation_element )
          .die( 'activate' )
          .live
          (
            'activate',
            function( event )
            {
              $( this ).addClass( 'current' );
              init_tree( $( '#tree-content', cloud_element ) );
            }
          );

        $( '.graph', navigation_element )
          .die( 'activate' )
          .live
          (
            'activate',
            function( event )
            {
              $( this ).addClass( 'current' );
              init_graph( $( '#graph-content', cloud_element ) );
            }
          );

        $( 'a[href="' + context.path + '"]', navigation_element )
          .trigger( 'activate' );

      }
    );
  }
);<commit_msg>SOLR-3339: Use solr_path instead of core_basepath for Cloud-View<commit_after>/*
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

var init_debug = function( cloud_element )
{
  var debug_element = $( '#debug', cloud_element );
  var debug_button = $( '.dump a', cloud_element );

  var clipboard_element = $( '.clipboard', debug_element );
  var clipboard_button = $( 'a', clipboard_element );

  debug_button
    .die( 'click' )
    .live
    (
      'click',
      function( event )
      {
        debug_element.trigger( 'show' );
        return false;
      }
    );

  $( '.close', debug_element )
    .die( 'click' )
    .live
    (
      'click',
      function( event )
      {
        debug_element.trigger( 'hide' );
        return false;
      }
    );

  $( '.clipboard', debug_element )
    .die( 'click' )
    .live
    (
      'click',
      function( event )
      {
        return false;
      }
    );

  debug_element
    .die( 'show' )
    .live
    (
      'show',
      function( event )
      {
        debug_button.hide();
        debug_element.show();

        $.ajax
        (
          {
            url : app.config.solr_path + '/zookeeper?wt=json&dump=true',
            dataType : 'text',
            context : debug_element,
            beforeSend : function( xhr, settings )
            {
              $( '.debug', debug_element )
                .html( 'Loading Dump ...' );

              ZeroClipboard.setMoviePath( 'img/ZeroClipboard.swf' );

              clipboard_client = new ZeroClipboard.Client();

              clipboard_client.addEventListener
              (
                'load',
                function( client )
                {
                }
              );

              clipboard_client.addEventListener
              (
                'complete',
                function( client, text )
                {
                  clipboard_element
                    .addClass( 'copied' );

                  clipboard_button
                    .data( 'text', clipboard_button.text() )
                    .text( clipboard_button.data( 'copied' ) );
                }
              );
            },
            success : function( response, text_status, xhr )
            {
              clipboard_client.glue
              (
                clipboard_element.get(0),
                clipboard_button.get(0)
              );

              clipboard_client.setText( response.replace( /\\/g, '\\\\' ) );

              $( '.debug', debug_element )
                .removeClass( 'loader' )
                .text( response );
            },
            error : function( xhr, text_status, error_thrown )
            {
            },
            complete : function( xhr, text_status )
            {
            }
          }
        );
      }
    )
    .die( 'hide' )
    .live
    (
      'hide',
      function( event )
      {
        $( '.debug', debug_element )
          .empty();

        clipboard_element
          .removeClass( 'copied' );

        clipboard_button
          .data( 'copied', clipboard_button.text() )
          .text( clipboard_button.data( 'text' ) );

        clipboard_client.destroy();

        debug_button.show();
        debug_element.hide();
      }
    );
};

var generate_graph = function( graph_element, graph_data )
{
  var w = 900,
      h = 300;

  var tree = d3.layout.tree()
      .size([h, w - 400]);

  var diagonal = d3.svg.diagonal()
      .projection(function(d) { return [d.y, d.x]; });

  var vis = d3.select("#canvas").append("svg")
      .attr("width", w)
      .attr("height", h)
    .append("g")
      .attr("transform", "translate(100, 0)");

  var nodes = tree.nodes(graph_data);

  var link = vis.selectAll("path.link")
      .data(tree.links(nodes))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", diagonal);

  var node = vis.selectAll("g.node")
      .data(nodes)
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 4.5);

  node.append("text")
      .attr("dx", function(d) { return d.children ? -8 : 8; })
      .attr("dy", 3)
      .attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
      .text(function(d) { return d.name; });

  /*
  var r = 860 / 2;

  var tree = d3.layout.tree()
      .size([360, r - 120])
      .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });

  var diagonal = d3.svg.diagonal.radial()
      .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });

  var vis = d3.select("#canvas").append("svg")
      .attr("width", r * 2)
      .attr("height", r * 2 - 150)
    .append("g")
      .attr("transform", "translate(" + r + "," + r + ")");

  var nodes = tree.nodes(graph_data);

  var link = vis.selectAll("path.link")
      .data(tree.links(nodes))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", diagonal);

  var node = vis.selectAll("g.node")
      .data(nodes)
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })

  node.append("circle")
      .attr("r", 4.5);

  node.append("text")
      .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
      .attr("dy", ".31em")
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
      .text(function(d) { return d.name; });
  //*/

};

var init_graph = function( graph_element )
{
  $.ajax
  (
    {
      url : app.config.solr_path + '/zookeeper?wt=json&detail=true&path=%2Fclusterstate.json',
      dataType : 'json',
      context : graph_element,
      beforeSend : function( xhr, settings )
      {
        this
          .show();
      },
      success : function( response, text_status, xhr )
      {
        var state = null;
        eval( 'state = ' + response.znode.data + ';' );

        var collections = [];
        for( var c in state )
        {
          var shards = [];
          for( var s in state[c] )
          {
            var nodes = [];
            for( var n in state[c][s] )
            {
              var node = {
                id: state[c][s][n].node_name,
                name: state[c][s][n].base_url,
                data: {
                  type : 'node',
                  state : state[c][s][n].state,
                  leader : 'true' === state[c][s][n].leader
                }
              };
              nodes.push( node );
            }

            var shard = {
              id: s,
              name: s,
              data: {
                type : 'shard',
              },
              children: nodes
            };
            shards.push( shard );
          }

          var collection = {
            id: c,
            name: c,
            data: {
              type : 'collection',
            },
            children: shards
          };
          collections.push( collection );
        }

        var graph_data = collections.shift();
        generate_graph( graph_element, graph_data );
      },
      error : function( xhr, text_status, error_thrown)
      {
      },
      complete : function( xhr, text_status )
      {
      }
    }
  );

};

var init_tree = function( tree_element )
{
  $.ajax
  (
    {
      url : app.config.solr_path + '/zookeeper?wt=json',
      dataType : 'json',
      context : tree_element,
      beforeSend : function( xhr, settings )
      {
        this
          .show();
      },
      success : function( response, text_status, xhr )
      {
        var self = this;

        $( '#tree', this )
          .jstree
          (
            {
              "plugins" : [ "json_data" ],
              "json_data" : {
                "data" : response.tree,
                "progressive_render" : true
              },
              "core" : {
                "animation" : 0
              }
            }
          )
          .jstree
          (
            'open_node',
            'li:first'
          );

        var tree_links = $( '#tree a', this );

        tree_links
          .die( 'click' )
          .live
          (
            'click',
            function( event )
            {
              $( 'a.active', $( this ).parents( '#tree' ) )
                .removeClass( 'active' );

              $( this )
                .addClass( 'active' );

              tree_element
                .addClass( 'show' );

              var file_content = $( '#file-content' );

              $( 'a.close', file_content )
                .die( 'click' )
                .live
                (
                  'click',
                  function( event )
                  {
                    $( '#tree a.active' )
                      .removeClass( 'active' );

                    tree_element
                      .removeClass( 'show' );

                    return false;
                  }
                );

              $.ajax
              (
                {
                  url : this.href,
                  dataType : 'json',
                  context : file_content,
                  beforeSend : function( xhr, settings )
                  {
                  },
                  success : function( response, text_status, xhr )
                  {
                    var props = [];
                    for( var key in response.znode.prop )
                    {
                      props.push
                      (
                        '

' + "\n" +
                          '
' + key.esc() + '
' + "\n" +
                          '
' + response.znode.prop[key].esc() + '
' + "\n" +
                        '

'
                      );
                    }

                    $( '#prop ul', this )
                      .empty()
                      .html( props.join( "\n" ) );

                    $( '#prop ul li:odd', this )
                      .addClass( 'odd' );

                    var data_element = $( '#data', this );

                    if( 0 !== parseInt( response.znode.prop.children_count ) )
                    {
                      data_element.hide();
                    }
                    else
                    {
                      var highlight = false;
                      var data = 'File "' + response.znode.path + '" has no Content';

                      if( response.znode.data )
                      {
                        var classes = '';
                        var path = response.znode.path.split( '.' );

                        if( 1 < path.length )
                        {
                          highlight = true;
                          classes = 'syntax language-' + path.pop().esc();
                        }

                        data = '
'
                             + response.znode.data.esc()
                             + '
';
                      }

                      data_element
                          .show()
                          .html( data );

                      if( highlight )
                      {
                        hljs.highlightBlock( data_element.get(0) );
                      }
                    }
                  },
                  error : function( xhr, text_status, error_thrown)
                  {
                  },
                  complete : function( xhr, text_status )
                  {
                  }
                }
              );

              return false;
            }
          );
      },
      error : function( xhr, text_status, error_thrown )
      {
        var message = 'Loading of ' + app.config.zookeeper_path + ' failed with "' + text_status + '" '
                    + '(' + error_thrown.message + ')';

        if( 200 !== xhr.status )
        {
          message = 'Loading of ' + app.config.zookeeper_path + ' failed with HTTP-Status ' + xhr.status + ' ';
        }

        this
          .html( '
' + message + '
' );
      },
      complete : function( xhr, text_status )
      {
      }
    }
  );
};

// #/~cloud
sammy.get
(
  /^#\/~(cloud)$/,
  function( context )
  {
    var content_element = $( '#content' );

    $.get
    (
      'tpl/cloud.html',
      function( template )
      {
        content_element
          .html( template );

        var cloud_element = $( '#cloud', content_element );
        var navigation_element = $( '#navigation', content_element );

        init_debug( cloud_element );

        $( '.tree', navigation_element )
          .die( 'activate' )
          .live
          (
            'activate',
            function( event )
            {
              $( this ).addClass( 'current' );
              init_tree( $( '#tree-content', cloud_element ) );
            }
          );

        $( '.graph', navigation_element )
          .die( 'activate' )
          .live
          (
            'activate',
            function( event )
            {
              $( this ).addClass( 'current' );
              init_graph( $( '#graph-content', cloud_element ) );
            }
          );

        $( 'a[href="' + context.path + '"]', navigation_element )
          .trigger( 'activate' );

      }
    );
  }
);<|endoftext|>


<commit_before>module.exports = o => `<head>
    <title>Tennisvuorot Helsingissä</title>
    <meta charset="utf-8"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <link rel="apple-touch-icon" href="tennisBall.png"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="google" content="notranslate" />
    <meta name="Description" content="Helsingin tenniskenttien varaustilanne ja yhteystiedot.">
    <link rel="stylesheet" type="text/css" href="styles.css"/>
    <meta name="google-site-verification" content="KcIYdY4YdFSZqc7HCEJnLyFBDBvbEOxDq_1K9drmUPk" />
</head>`
<commit_msg>Remove meta tag for google<commit_after>module.exports = o => `<head>
    <title>Tennisvuorot Helsingissä</title>
    <meta charset="utf-8"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <link rel="apple-touch-icon" href="tennisBall.png"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="google" content="notranslate" />
    <meta name="Description" content="Helsingin tenniskenttien varaustilanne ja yhteystiedot.">
    <link rel="stylesheet" type="text/css" href="styles.css"/>
</head>`
<|endoftext|>


<commit_before>// Wrapper around Apple's Instruments app
"use strict";

var spawn = require('child_process').spawn
  , exec = require('child_process').exec
  , logger = require('../logger').get('appium')
  , fs = require('fs')
  , _ = require('underscore')
  , net = require('net')
  , uuid = require('uuid-js')
  , codes = require('../app/uiauto/lib/status.js').codes;

var Instruments = function(app, udid, bootstrap, template, sock, withoutDelay, cb, exitCb) {
  this.app = app;
  this.udid = udid;
  this.bootstrap = bootstrap;
  this.template = template;
  this.withoutDelay = withoutDelay;
  this.commandQueue = [];
  this.curCommand = null;
  this.resultHandler = this.defaultResultHandler;
  this.readyHandler = this.defaultReadyHandler;
  this.exitHandler = this.defaultExitHandler;
  this.hasConnected = false;
  this.traceDir = null;
  this.proc = null;
  this.debugMode = false;
  this.onReceiveCommand = null;
  this.guid = uuid.create();
  this.bufferedData = "";
  this.instrumentsPath = "";
  this.eventRouter = {
    'cmd': this.commandHandler
  };
  this.socketServer = null;
  if (typeof sock === "undefined") {
    sock = '/tmp/instruments_sock';
  }
  if (typeof cb !== "undefined") {
    this.readyHandler = cb;
  }
  if (typeof exitCb !== "undefined") {
    this.exitHandler = exitCb;
  }

  this.startSocketServer(sock);

};

/* INITIALIZATION */

Instruments.prototype.startSocketServer = function(sock) {
  // remove socket if it currently exists
  try {
    fs.unlinkSync(sock);
  } catch (Exception) {}

  var onSocketNeverConnect = function() {
    logger.error("Instruments socket client never checked in; timing out".red);
    this.proc.kill('SIGTERM');
    this.exitHandler(1);
  };

  var socketConnectTimeout = setTimeout(_.bind(onSocketNeverConnect, this), 300000);

  this.socketServer = net.createServer({allowHalfOpen: true}, _.bind(function(conn) {
    if (!this.hasConnected) {
      this.hasConnected = true;
      this.debug("Instruments is ready to receive commands");
      clearTimeout(socketConnectTimeout);
      this.readyHandler(this);
      this.readyHandler = this.defaultReadyHandler;
    }
    conn.setEncoding('utf8'); // get strings from sockets rather than buffers

    conn.on('data', _.bind(function(data) {
      // when data comes in, route it according to the "event" property
      this.debug("Socket data received (" + data.length + " bytes)");
      this.bufferedData += data;
    }, this));

    this.currentSocket = conn;
    //this.debug("Socket Connected");

    conn.on('close', _.bind(function() {
        //this.debug("Socket Completely closed");
        this.currentSocket = null;
    }, this));

    conn.on('end', _.bind(function() {
      //this.debug("Socket closed by other side");
      var data = this.bufferedData;
      this.bufferedData = "";
      try {
        data = JSON.parse(data);
      } catch (e) {
        logger.error("Couldn't parse JSON data from socket, maybe buffer issue?");
        logger.error(data);
        data = {
          event: 'cmd'
          , result: {
            status: codes.UnknownError
            , value: "Error parsing socket data from instruments"
          }
        };
      }
      if (!_.has(data, 'event')) {
        logger.error("Socket data came in witout event, it was:");
        logger.error(JSON.stringify(data));
      } else if (!_.has(this.eventRouter, data.event)) {
        logger.error("Socket is asking for event '" + data.event +
                    "' which doesn't exist");
      } else {
        this.debug("Socket data being routed for '" + data.event + "' event");
        _.bind(this.eventRouter[data.event], this)(data, conn);
      }
    }, this));

  }, this));

  this.socketServer.on('close', _.bind(function() {
    this.debug("Instruments socket server closed");
  }, this));

  exec('xcrun -find instruments', _.bind(function (error, stdout) {
    this.instrumentsPath = stdout.trim();
    logger.info("instruments is: " + this.instrumentsPath);

    this.socketServer.listen(sock, _.bind(function() {
      this.debug("Instruments socket server started at " + sock);
      this.launch();
    }, this));
  }, this));
};

Instruments.prototype.launch = function() {
  var self = this;
  // prepare temp dir
  var tmpDir = '/tmp/' + this.guid;
  fs.mkdir(tmpDir, function(e) {
    if (!e || (e && e.code === 'EEXIST')) {
      self.proc = self.spawnInstruments(tmpDir);
      self.proc.stdout.on('data', function(data) {
        self.outputStreamHandler(data);
      });
      self.proc.stderr.on('data', function(data) {
        self.errorStreamHandler(data);
      });

      self.proc.on('exit', function(code) {
        self.debug("Instruments exited with code " + code);
        self.exitCode = code;
        self.exitHandler(self.exitCode, self.traceDir);
        self.proc.stdin.end();
        self.proc = null;
        self.exitHandler = self.defaultExitHandler;
        self.resultHandler = self.defaultResultHandler;
        self.onReceiveCommand = null;
        if (self.currentSocket) {
          self.debug("Socket closed forcibly due to exit");
          self.currentSocket.end();
          self.currentSocket.destroy(); // close this
          self.socketServer.close();
        }
      });
    } else {
      throw e;
    }
  });
};

Instruments.prototype.spawnInstruments = function(tmpDir) {
  var args = ["-t", this.template];
  if (this.udid) {
    args = args.concat(["-w", this.udid]);
    logger.info("Attempting to run app on real device with UDID " + this.udid);
  }
  args = args.concat([this.app]);
  args = args.concat(["-e", "UIASCRIPT", this.bootstrap]);
  args = args.concat(["-e", "UIARESULTSPATH", tmpDir]);
  var env = _.clone(process.env);
  if (this.withoutDelay) {
    env.DYLD_INSERT_LIBRARIES = "./submodules/instruments-without-delay/build/InstrumentsShim.dylib";
    env.LIB_PATH = "./submodules/instruments-without-delay/build";
  }
  return spawn(this.instrumentsPath, args, {env: env});
};

/* COMMAND LIFECYCLE */

Instruments.prototype.commandHandler = function(data, c) {
  var hasResult = typeof data.result !== "undefined";
  if (hasResult && !this.curCommand) {
    logger.info("Got a result when we weren't expecting one! Ignoring it");
  } else if (!hasResult && this.curCommand) {
    logger.info("Instruments didn't send a result even though we were expecting one");
    hasResult = true;
    data.result = false;
  }

  if (hasResult) {
    if (data.result) {
      this.debug("Got result from instruments: " + JSON.stringify(data.result));
    } else {
      this.debug("Got null result from instruments");
    }
    this.curCommand.cb(data.result);
    this.curCommand = null;
  }

  this.waitForCommand(_.bind(function() {
    this.curCommand = this.commandQueue.shift();
    this.onReceiveCommand = null;
    this.debug("Sending command to instruments: " + this.curCommand.cmd);
    c.write(JSON.stringify({nextCommand: this.curCommand.cmd}));
    c.end();
    //this.debug("Closing our half of the connection");
  }, this));
};

Instruments.prototype.waitForCommand = function(cb) {
  if (this.commandQueue.length) {
    cb();
  } else {
    this.onReceiveCommand = cb;
  }
};

Instruments.prototype.sendCommand = function(cmd, cb) {
  this.commandQueue.push({cmd: cmd, cb: cb});
  if (this.onReceiveCommand) {
    this.onReceiveCommand();
  }
};

/* PROCESS MANAGEMENT */

Instruments.prototype.shutdown = function() {
  this.proc.kill();
};

Instruments.prototype.doExit = function() {
  console.log("Calling exit handler");
};

/* INSTRUMENTS STREAM MANIPULATION*/

Instruments.prototype.clearBufferChars = function(output) {
  // Instruments output is buffered, so for each log output we also output
  // a stream of very many ****. This function strips those out so all we
  // get is the log output we care about
  var re = /(\n|^)\*+\n?/g;
  output = output.toString();
  output = output.replace(re, "");
  return output;
};

Instruments.prototype.outputStreamHandler = function(output) {
  output = this.clearBufferChars(output);
  this.lookForShutdownInfo(output);
  this.resultHandler(output);
};

Instruments.prototype.errorStreamHandler = function(output) {
  logger.info(("[INST STDERR] " + output).yellow);
};

Instruments.prototype.lookForShutdownInfo = function(output) {
  var re = /Instruments Trace Complete.+Output : ([^\)]+)\)/;
  var match = re.exec(output);
  if (match) {
    this.traceDir = match[1];
  }
};

/* DEFAULT HANDLERS */

Instruments.prototype.setResultHandler = function(handler) {
  this.resultHandler = handler;
};

Instruments.prototype.defaultResultHandler = function(output) {
  // if we have multiple log lines, indent non-first ones
  if (output !== "") {
    output = output.replace(/\n/m, "\n       ");
    logger.info(("[INST] " + output).green);
  }
};

Instruments.prototype.defaultReadyHandler = function() {
  logger.info("Instruments is ready and waiting!");
};

Instruments.prototype.defaultExitHandler = function(code, traceDir) {
  logger.info("Instruments exited with code " + code + " and trace dir " + traceDir);
};

/* MISC */

Instruments.prototype.setDebug = function(debug) {
  if (typeof debug === "undefined") {
    debug = true;
  }
  this.debugMode = debug;
};

Instruments.prototype.debug = function(msg) {
  logger.info(("[INSTSERVER] " + msg).grey);
};

/* NODE EXPORTS */

module.exports = function(server, app, udid, bootstrap, template, sock, cb, exitCb) {
  return new Instruments(server, app, udid, bootstrap, template, sock, cb, exitCb);
};

<commit_msg>resolve paths relative to __dirname so we don't depend on the cwd<commit_after>// Wrapper around Apple's Instruments app
"use strict";

var spawn = require('child_process').spawn
  , exec = require('child_process').exec
  , logger = require('../logger').get('appium')
  , fs = require('fs')
  , _ = require('underscore')
  , net = require('net')
  , uuid = require('uuid-js')
  , path = require('path')
  , codes = require('../app/uiauto/lib/status.js').codes;

var Instruments = function(app, udid, bootstrap, template, sock, withoutDelay, cb, exitCb) {
  this.app = app;
  this.udid = udid;
  this.bootstrap = bootstrap;
  this.template = template;
  this.withoutDelay = withoutDelay;
  this.commandQueue = [];
  this.curCommand = null;
  this.resultHandler = this.defaultResultHandler;
  this.readyHandler = this.defaultReadyHandler;
  this.exitHandler = this.defaultExitHandler;
  this.hasConnected = false;
  this.traceDir = null;
  this.proc = null;
  this.debugMode = false;
  this.onReceiveCommand = null;
  this.guid = uuid.create();
  this.bufferedData = "";
  this.instrumentsPath = "";
  this.eventRouter = {
    'cmd': this.commandHandler
  };
  this.socketServer = null;
  if (typeof sock === "undefined") {
    sock = '/tmp/instruments_sock';
  }
  if (typeof cb !== "undefined") {
    this.readyHandler = cb;
  }
  if (typeof exitCb !== "undefined") {
    this.exitHandler = exitCb;
  }

  this.startSocketServer(sock);

};

/* INITIALIZATION */

Instruments.prototype.startSocketServer = function(sock) {
  // remove socket if it currently exists
  try {
    fs.unlinkSync(sock);
  } catch (Exception) {}

  var onSocketNeverConnect = function() {
    logger.error("Instruments socket client never checked in; timing out".red);
    this.proc.kill('SIGTERM');
    this.exitHandler(1);
  };

  var socketConnectTimeout = setTimeout(_.bind(onSocketNeverConnect, this), 300000);

  this.socketServer = net.createServer({allowHalfOpen: true}, _.bind(function(conn) {
    if (!this.hasConnected) {
      this.hasConnected = true;
      this.debug("Instruments is ready to receive commands");
      clearTimeout(socketConnectTimeout);
      this.readyHandler(this);
      this.readyHandler = this.defaultReadyHandler;
    }
    conn.setEncoding('utf8'); // get strings from sockets rather than buffers

    conn.on('data', _.bind(function(data) {
      // when data comes in, route it according to the "event" property
      this.debug("Socket data received (" + data.length + " bytes)");
      this.bufferedData += data;
    }, this));

    this.currentSocket = conn;
    //this.debug("Socket Connected");

    conn.on('close', _.bind(function() {
        //this.debug("Socket Completely closed");
        this.currentSocket = null;
    }, this));

    conn.on('end', _.bind(function() {
      //this.debug("Socket closed by other side");
      var data = this.bufferedData;
      this.bufferedData = "";
      try {
        data = JSON.parse(data);
      } catch (e) {
        logger.error("Couldn't parse JSON data from socket, maybe buffer issue?");
        logger.error(data);
        data = {
          event: 'cmd'
          , result: {
            status: codes.UnknownError
            , value: "Error parsing socket data from instruments"
          }
        };
      }
      if (!_.has(data, 'event')) {
        logger.error("Socket data came in witout event, it was:");
        logger.error(JSON.stringify(data));
      } else if (!_.has(this.eventRouter, data.event)) {
        logger.error("Socket is asking for event '" + data.event +
                    "' which doesn't exist");
      } else {
        this.debug("Socket data being routed for '" + data.event + "' event");
        _.bind(this.eventRouter[data.event], this)(data, conn);
      }
    }, this));

  }, this));

  this.socketServer.on('close', _.bind(function() {
    this.debug("Instruments socket server closed");
  }, this));

  exec('xcrun -find instruments', _.bind(function (error, stdout) {
    this.instrumentsPath = stdout.trim();
    logger.info("instruments is: " + this.instrumentsPath);

    this.socketServer.listen(sock, _.bind(function() {
      this.debug("Instruments socket server started at " + sock);
      this.launch();
    }, this));
  }, this));
};

Instruments.prototype.launch = function() {
  var self = this;
  // prepare temp dir
  var tmpDir = '/tmp/' + this.guid;
  fs.mkdir(tmpDir, function(e) {
    if (!e || (e && e.code === 'EEXIST')) {
      self.proc = self.spawnInstruments(tmpDir);
      self.proc.stdout.on('data', function(data) {
        self.outputStreamHandler(data);
      });
      self.proc.stderr.on('data', function(data) {
        self.errorStreamHandler(data);
      });

      self.proc.on('exit', function(code) {
        self.debug("Instruments exited with code " + code);
        self.exitCode = code;
        self.exitHandler(self.exitCode, self.traceDir);
        self.proc.stdin.end();
        self.proc = null;
        self.exitHandler = self.defaultExitHandler;
        self.resultHandler = self.defaultResultHandler;
        self.onReceiveCommand = null;
        if (self.currentSocket) {
          self.debug("Socket closed forcibly due to exit");
          self.currentSocket.end();
          self.currentSocket.destroy(); // close this
          self.socketServer.close();
        }
      });
    } else {
      throw e;
    }
  });
};

Instruments.prototype.spawnInstruments = function(tmpDir) {
  var args = ["-t", this.template];
  if (this.udid) {
    args = args.concat(["-w", this.udid]);
    logger.info("Attempting to run app on real device with UDID " + this.udid);
  }
  args = args.concat([this.app]);
  args = args.concat(["-e", "UIASCRIPT", this.bootstrap]);
  args = args.concat(["-e", "UIARESULTSPATH", tmpDir]);
  var env = _.clone(process.env);
  if (this.withoutDelay) {
    env.DYLD_INSERT_LIBRARIES = path.resolve(__dirname, "../submodules/instruments-without-delay/build/InstrumentsShim.dylib");
    env.LIB_PATH = path.resolve(__dirname, "../submodules/instruments-without-delay/build");
  }
  return spawn(this.instrumentsPath, args, {env: env});
};

/* COMMAND LIFECYCLE */

Instruments.prototype.commandHandler = function(data, c) {
  var hasResult = typeof data.result !== "undefined";
  if (hasResult && !this.curCommand) {
    logger.info("Got a result when we weren't expecting one! Ignoring it");
  } else if (!hasResult && this.curCommand) {
    logger.info("Instruments didn't send a result even though we were expecting one");
    hasResult = true;
    data.result = false;
  }

  if (hasResult) {
    if (data.result) {
      this.debug("Got result from instruments: " + JSON.stringify(data.result));
    } else {
      this.debug("Got null result from instruments");
    }
    this.curCommand.cb(data.result);
    this.curCommand = null;
  }

  this.waitForCommand(_.bind(function() {
    this.curCommand = this.commandQueue.shift();
    this.onReceiveCommand = null;
    this.debug("Sending command to instruments: " + this.curCommand.cmd);
    c.write(JSON.stringify({nextCommand: this.curCommand.cmd}));
    c.end();
    //this.debug("Closing our half of the connection");
  }, this));
};

Instruments.prototype.waitForCommand = function(cb) {
  if (this.commandQueue.length) {
    cb();
  } else {
    this.onReceiveCommand = cb;
  }
};

Instruments.prototype.sendCommand = function(cmd, cb) {
  this.commandQueue.push({cmd: cmd, cb: cb});
  if (this.onReceiveCommand) {
    this.onReceiveCommand();
  }
};

/* PROCESS MANAGEMENT */

Instruments.prototype.shutdown = function() {
  this.proc.kill();
};

Instruments.prototype.doExit = function() {
  console.log("Calling exit handler");
};

/* INSTRUMENTS STREAM MANIPULATION*/

Instruments.prototype.clearBufferChars = function(output) {
  // Instruments output is buffered, so for each log output we also output
  // a stream of very many ****. This function strips those out so all we
  // get is the log output we care about
  var re = /(\n|^)\*+\n?/g;
  output = output.toString();
  output = output.replace(re, "");
  return output;
};

Instruments.prototype.outputStreamHandler = function(output) {
  output = this.clearBufferChars(output);
  this.lookForShutdownInfo(output);
  this.resultHandler(output);
};

Instruments.prototype.errorStreamHandler = function(output) {
  logger.info(("[INST STDERR] " + output).yellow);
};

Instruments.prototype.lookForShutdownInfo = function(output) {
  var re = /Instruments Trace Complete.+Output : ([^\)]+)\)/;
  var match = re.exec(output);
  if (match) {
    this.traceDir = match[1];
  }
};

/* DEFAULT HANDLERS */

Instruments.prototype.setResultHandler = function(handler) {
  this.resultHandler = handler;
};

Instruments.prototype.defaultResultHandler = function(output) {
  // if we have multiple log lines, indent non-first ones
  if (output !== "") {
    output = output.replace(/\n/m, "\n       ");
    logger.info(("[INST] " + output).green);
  }
};

Instruments.prototype.defaultReadyHandler = function() {
  logger.info("Instruments is ready and waiting!");
};

Instruments.prototype.defaultExitHandler = function(code, traceDir) {
  logger.info("Instruments exited with code " + code + " and trace dir " + traceDir);
};

/* MISC */

Instruments.prototype.setDebug = function(debug) {
  if (typeof debug === "undefined") {
    debug = true;
  }
  this.debugMode = debug;
};

Instruments.prototype.debug = function(msg) {
  logger.info(("[INSTSERVER] " + msg).grey);
};

/* NODE EXPORTS */

module.exports = function(server, app, udid, bootstrap, template, sock, cb, exitCb) {
  return new Instruments(server, app, udid, bootstrap, template, sock, cb, exitCb);
};

<|endoftext|>


<commit_before>const Request = require('./request')

class LineBot {

  constructor(credentials) {
    this._credentials = credentials
    if (!this._credentials) {
      throw new Error("InvalidCredentialsError")
    }
  }

  _getCredential(credentialKey) {
    return this._credentials[credentialKey]
  }

  getChannelToken() {
    return this._getCredential('channelToken')
  }

  getChannelSecret() {
    return this._getCredential('channelSecret')
  }

  replyMessage() {
    'https://api.line.me/v2/bot/message/reply'
  }

  pushMessage(userId, messages) {
    const data = {
      "to": userId,
      "messages": Array.isArray(messages) ? messages : [messages]
    }
    const request = new Request('/v2/bot/message/push', this.getChannelToken(), data)
    return request.post()
  }

  getProfiole(userId) {
    const path = '/v2/bot/profile/' + userId
    const request = new Request(path, this.getChannelToken())
    return request.get()
  }

  getContent(messageId) {
    const path = '/v2/bot/message/' + messageId + '/content'
    const request = new Request(path, this.getChannelToken())
    return request.get()
  }

  leaveRoom(roomId) {
    const path = '/v2/bot/room/' + roomId + '/leave'
    const request = new Request(path, this.getChannelToken())
    return request.post()
  }
}

module.exports = LineBot
<commit_msg>develop replyMessage<commit_after>const Request = require('./request')

class LineBot {

  constructor(credentials) {
    this._credentials = credentials
    if (!this._credentials) {
      throw new Error("InvalidCredentialsError")
    }
  }

  _getCredential(credentialKey) {
    return this._credentials[credentialKey]
  }

  getChannelToken() {
    return this._getCredential('channelToken')
  }

  getChannelSecret() {
    return this._getCredential('channelSecret')
  }

  replyMessage(replyToken, messages) {
    const data = {
      "replyToken": replyToken,
      "messages": Array.isArray(messages) ? messages : [messages]
    }
    const request = new Request('/v2/bot/message/reply', this.getChannelToken(), data)
    return request.post()
  }

  pushMessage(userId, messages) {
    const data = {
      "to": userId,
      "messages": Array.isArray(messages) ? messages : [messages]
    }
    const request = new Request('/v2/bot/message/push', this.getChannelToken(), data)
    return request.post()
  }

  getProfiole(userId) {
    const path = '/v2/bot/profile/' + userId
    const request = new Request(path, this.getChannelToken())
    return request.get()
  }

  getContent(messageId) {
    const path = '/v2/bot/message/' + messageId + '/content'
    const request = new Request(path, this.getChannelToken())
    return request.get()
  }

  leaveRoom(roomId) {
    const path = '/v2/bot/room/' + roomId + '/leave'
    const request = new Request(path, this.getChannelToken())
    return request.post()
  }
}

module.exports = LineBot
<|endoftext|>


<commit_before>/*
tutorial-embeds.js
tutorial-embeds.css
author: Peter Richardson 2017
contact: peter@mapzen.com

This code was written for use in Tangram tutorials pages to allow multiple Tangram Play embeds on a page while limiting resource usage. It expects a number of target divs on a page, each with class="demo", an empty "code" attribute, and a "source" attribute which is to be the "src" of a loaded iframe.

It creates a number of iframes (set by the numberOfFrames variable) and moves them from place to place, setting the src of each. It then saves any changes made in the Play editor to the "code" attribute, and if that frame is loaded again later it uses that attribute to restore the code.

Example div:

*/

var frames = [];
var winners = [];
var loaders = [];
var numberOfFrames = 3;

// find distance of element from center of viewport
function distanceFromCenter(el) {
    var top = el.offsetTop;
    var height = el.offsetHeight;

    while(el.offsetParent) {
        el = el.offsetParent;
        top += el.offsetTop;
    }

    var windowCenter = window.pageYOffset + window.innerHeight/2;
    var elementCenter = top + height/2;

    return Math.abs(windowCenter - elementCenter);
}

function moveFrameToElement(frame, el) {
    if (typeof el == 'undefined') return false;
    newtop = el.offsetTop;
    frame.style.top = newtop+"px";
    frame.style.left = el.offsetLeft+"px";
    // get the source if it has been set
    if (typeof el.getAttribute("source") != 'undefined') {
        frame.src = el.getAttribute("source");
    }
    // if code was saved previously, load it
    if (el.getAttribute("code") !='' && el.getAttribute("code") != 'null') {
        loadOldCode(frame, el);
    } else {
        // show the iframe once it's loaded
        frame.onload = function() {
            frame.style.visibility = "visible";
            // for safari
            frame.style.height = "";
        }
    }
}

function loadOldCode(frame, el) {
    // get source from the previously-saved blobURL
    var code = el.getAttribute("code");
    if (typeof code == 'undefined') return false;
    frame.onload = function() {
        // if the contentWindow doesn't exist, bail
        if (typeof frame.contentWindow == 'undefined') {
            console.log('is frame.contentWindow undefined?', frame.contentWindow);
            return false;
        }
        // set the value of the codeMirror editor
        var editor = frame.contentWindow.editor;
        var scene;

        // wait for Tangram's leafletLayer to be defined
        if (frame.contentWindow.layer) {
            setTimeout(function() {
                // use a setTimeout 0 to make this a separate entry in the browser's event queue, so it won't happen until the editor is ready
                setCode(code);
            }, 0);
        } else {
            Object.defineProperty(frame.contentWindow, 'layer', {
                configurable: true,
                enumerable: true,
                writeable: true,
                get: function() {
                    return this._layer;
                },
                set: function(val) {
                    this._layer = val;
                    setCode(code);
                }
            });
        }

        // create an event
        var load_event = { load: function() {
                // immediately unsubscribe
                scene.unsubscribe(this);
                // put the old code in the editor pane
                editor.doc.setValue(code);
            }};

        function setCode(code) {
            try {
                scene = frame.contentWindow.layer.scene;
            } catch(e) {
            }
            if (scene && scene.initializing) {
                // Tangram ain't ready - subscribe to its load_event
                scene.subscribe(load_event);
            } else {
                // put the old code in the editor pane
                editor.doc.setValue(code);
            }
        }

        // show iframe
        frame.style.visibility = "visible";
        // for safari
        frame.style.height = "";
    }
}

window.onload = function() {
    // create new iframes
    for (x = 0; x < numberOfFrames; x++) {
        frames[x] = document.createElement("iframe");
        frames[x].classList.add("demoframeclass");
        frames[x].setAttribute("id", "frame"+x);
        document.getElementsByClassName("documentation-content")[0].appendChild(frames[x]);
        loaders[x] = document.createElement("div");
        loaders[x].classList.add("demo-loading");
    }

    checkVis();

    // throttle checkVis function
    window.onscroll = throttle(function() {checkVis()}, 250);

    function throttle(fn, threshhold, scope) {
      threshhold || (threshhold = 250);
      var last,
          deferTimer;
      return function () {
        var context = scope || this;

        var now = +new Date,
            args = arguments;
        if (last && now < last + threshhold) {
          // hold on to it
          clearTimeout(deferTimer);
          deferTimer = setTimeout(function () {
            last = now;
            fn.apply(context, args);
          }, threshhold);
        } else {
          last = now;
          fn.apply(context, args);
        }
      };
    }

    // check visibility of demos - show ones closest to the center of the viewport and hide the others to go easy on the GPU
    function checkVis() {
        var elements = document.getElementsByClassName("demo");
        var ranking = [];
        // sort frame wrappers by distance from center of screen
        for (var i=0; i < elements.length; i++) {
            el = elements[i];
            dist = distanceFromCenter(el);
            ranking.push([el, dist]);
            if (typeof el.demoframe == 'undefined') el.demoframe = null;
        }
        ranking.sort(function(a, b) {
            return a[1] - b[1]
        });
        // add the top ranked to the winners list
        for (var i=0; i < frames.length; i++) {
            winners[i] = ranking[i][0];
        }
        // clear the demoframe property of the others
        for (var i=winners.length; i < ranking.length; i++) {
            ranking[i][0].demoframe = null;
        }
        // for each winner, place a frame
        for (var i=0; i < winners.length; i++) {
            // if there's already a frame there, move on
            if (winners[i].demoframe != null) {
                continue;
            }
            // place each frame at a winner
            for (var j=0; j < frames.length; j++) {
                var safeword = false;
                // check to see if it's already at one of the winners
                for (var k=0; k < winners.length; k++) {
                    // if so, skip it
                    if (frames[j].element == winners[k]) {
                        safeword = true;
                        break;
                    }
                }
                // if the safeword was triggered, move to the next winner
                if (safeword) continue;
                // hide the demoframe
                frames[j].style.visibility = "hidden";
                // for safari
                frames[j].style.height = "0px";
                // remove any onloads in case it's in the middle of loading something
                frames[j].onload = null;
                // save current code state in a property called "code" on the parent div
                if (typeof frames[j].contentWindow.scene != 'undefined') {
                    frames[j].element.setAttribute("code", frames[j].contentWindow.editor.getValue());
                }
                // add demoframe and winner as properties of each other for tracking
                frames[j].element = winners[i];
                winners[i].demoframe = frames[j];

                // add a loading bar to the destination element
                winners[i].appendChild(loaders[i]);
                // move the demoframe
                moveFrameToElement(frames[j], winners[i]);
                break;
            }
        }
    };
}<commit_msg>debugging<commit_after>/*
tutorial-embeds.js
tutorial-embeds.css
author: Peter Richardson 2017
contact: peter@mapzen.com

This code was written for use in Tangram tutorials pages to allow multiple Tangram Play embeds on a page while limiting resource usage. It expects a number of target divs on a page, each with class="demo", an empty "code" attribute, and a "source" attribute which is to be the "src" of a loaded iframe.

It creates a number of iframes (set by the numberOfFrames variable) and moves them from place to place, setting the src of each. It then saves any changes made in the Play editor to the "code" attribute, and if that frame is loaded again later it uses that attribute to restore the code.

Example div:

*/

var frames = [];
var winners = [];
var loaders = [];
var numberOfFrames = 3;

// find distance of element from center of viewport
function distanceFromCenter(el) {
    var top = el.offsetTop;
    var height = el.offsetHeight;

    while(el.offsetParent) {
        el = el.offsetParent;
        top += el.offsetTop;
    }

    var windowCenter = window.pageYOffset + window.innerHeight/2;
    var elementCenter = top + height/2;

    return Math.abs(windowCenter - elementCenter);
}

function moveFrameToElement(frame, el) {
    if (typeof el == 'undefined') return false;
    newtop = el.offsetTop;
    frame.style.top = newtop+"px";
    frame.style.left = el.offsetLeft+"px";
    // get the source if it has been set
    if (typeof el.getAttribute("source") != 'undefined') {
        frame.src = el.getAttribute("source");
    }
    // if code was saved previously, load it
    if (el.getAttribute("code") !='' && el.getAttribute("code") != 'null') {
        loadOldCode(frame, el);
    } else {
        // show the iframe once it's loaded
        frame.onload = function() {
            frame.style.visibility = "visible";
            // for safari
            frame.style.height = "";
        }
    }
}

function loadOldCode(frame, el) {
    // get source from the previously-saved blobURL
    var code = el.getAttribute("code");
    if (typeof code == 'undefined') return false;
    frame.onload = function() {
        // if the contentWindow doesn't exist, bail
        if (typeof frame.contentWindow == 'undefined') {
            console.log('is frame.contentWindow undefined?', frame.contentWindow);
            return false;
        }
        // set the value of the codeMirror editor
        var editor = frame.contentWindow.editor;
        var scene;

        // wait for Tangram's leafletLayer to be defined
        if (frame.contentWindow.layer) {
            console.log('layer already exists')
            setTimeout(function() {
                // use a setTimeout 0 to make this a separate entry in the browser's event queue, so it won't happen until the editor is ready
                setCode(code);
            }, 0);
        } else {
            Object.defineProperty(frame.contentWindow, 'layer', {
                configurable: true,
                enumerable: true,
                writeable: true,
                get: function() {
                    return this._layer;
                },
                set: function(val) {
                    console.log('waited for layer')
                    this._layer = val;
                    setCode(code);
                }
            });
        }

        // create an event
        var load_event = { load: function() {
                console.log('waited for tangram')
                // immediately unsubscribe
                scene.unsubscribe(this);
                // put the old code in the editor pane
                editor.doc.setValue(code);
            }};

        function setCode(code) {
            try {
                scene = frame.contentWindow.layer.scene;
            } catch(e) {
            }
            if (scene && scene.initializing) {
                console.log("tangram exists but ain;t ready")
                // Tangram ain't ready - subscribe to its load_event
                scene.subscribe(load_event);
            } else {
                console.log('tangram already exists')

                // put the old code in the editor pane
                editor.doc.setValue(code);
            }
        }

        // show iframe
        frame.style.visibility = "visible";
        // for safari
        frame.style.height = "";
    }
}

window.onload = function() {
    // create new iframes
    for (x = 0; x < numberOfFrames; x++) {
        frames[x] = document.createElement("iframe");
        frames[x].classList.add("demoframeclass");
        frames[x].setAttribute("id", "frame"+x);
        document.getElementsByClassName("documentation-content")[0].appendChild(frames[x]);
        loaders[x] = document.createElement("div");
        loaders[x].classList.add("demo-loading");
    }

    checkVis();

    // throttle checkVis function
    window.onscroll = throttle(function() {checkVis()}, 250);

    function throttle(fn, threshhold, scope) {
      threshhold || (threshhold = 250);
      var last,
          deferTimer;
      return function () {
        var context = scope || this;

        var now = +new Date,
            args = arguments;
        if (last && now < last + threshhold) {
          // hold on to it
          clearTimeout(deferTimer);
          deferTimer = setTimeout(function () {
            last = now;
            fn.apply(context, args);
          }, threshhold);
        } else {
          last = now;
          fn.apply(context, args);
        }
      };
    }

    // check visibility of demos - show ones closest to the center of the viewport and hide the others to go easy on the GPU
    function checkVis() {
        var elements = document.getElementsByClassName("demo");
        var ranking = [];
        // sort frame wrappers by distance from center of screen
        for (var i=0; i < elements.length; i++) {
            el = elements[i];
            dist = distanceFromCenter(el);
            ranking.push([el, dist]);
            if (typeof el.demoframe == 'undefined') el.demoframe = null;
        }
        ranking.sort(function(a, b) {
            return a[1] - b[1]
        });
        // add the top ranked to the winners list
        for (var i=0; i < frames.length; i++) {
            winners[i] = ranking[i][0];
        }
        // clear the demoframe property of the others
        for (var i=winners.length; i < ranking.length; i++) {
            ranking[i][0].demoframe = null;
        }
        // for each winner, place a frame
        for (var i=0; i < winners.length; i++) {
            // if there's already a frame there, move on
            if (winners[i].demoframe != null) {
                continue;
            }
            // place each frame at a winner
            for (var j=0; j < frames.length; j++) {
                var safeword = false;
                // check to see if it's already at one of the winners
                for (var k=0; k < winners.length; k++) {
                    // if so, skip it
                    if (frames[j].element == winners[k]) {
                        safeword = true;
                        break;
                    }
                }
                // if the safeword was triggered, move to the next winner
                if (safeword) continue;
                // hide the demoframe
                frames[j].style.visibility = "hidden";
                // for safari
                frames[j].style.height = "0px";
                // remove any onloads in case it's in the middle of loading something
                frames[j].onload = null;
                // save current code state in a property called "code" on the parent div
                if (typeof frames[j].contentWindow.scene != 'undefined') {
                    frames[j].element.setAttribute("code", frames[j].contentWindow.editor.getValue());
                }
                // add demoframe and winner as properties of each other for tracking
                frames[j].element = winners[i];
                winners[i].demoframe = frames[j];

                // add a loading bar to the destination element
                winners[i].appendChild(loaders[i]);
                // move the demoframe
                moveFrameToElement(frames[j], winners[i]);
                break;
            }
        }
    };
}<|endoftext|>


<commit_before>(function() {
// if google maps is not defined do not load the class
if(typeof(google) == "undefined" || typeof(google.maps) == "undefined")
  return;

// helper to get pixel position from latlon
var Projector = function(map) { this.setMap(map); };
Projector.prototype = new google.maps.OverlayView();
Projector.prototype.draw = function() {};
Projector.prototype.latLngToPixel = function(point) {
  var p = this.getProjection();
  if(p) {
    return p.fromLatLngToContainerPixel(point);
  }
  return [0, 0];
};
Projector.prototype.pixelToLatLng = function(point) {
  var p = this.getProjection();
  if(p) {
    return p.fromContainerPixelToLatLng(point);
  }
  return [0, 0];
  //return this.map.getProjection().fromPointToLatLng(point);
};

var CartoDBLayer = function(opts) {

  var default_options = {
    query:          "SELECT * FROM {{table_name}}",
    attribution:    "CartoDB",
    opacity:        1,
    auto_bound:     false,
    debug:          false,
    visible:        true,
    added:          false,
    loaded:         null,
    loading:        null,
    layer_order:    "top",
    tiler_domain:   "cartodb.com",
    tiler_port:     "80",
    tiler_protocol: "http",
    sql_domain:     "cartodb.com",
    sql_port:       "80",
    sql_protocol:   "http",
    subdomains:      null
  };

  this.options = _.defaults(opts, default_options);
  opts.tiles = this._tileJSON().tiles;

  // Set init
  this.tiles = 0;

  // Add CartoDB logo
  this._addWadus({left: 74, bottom:8}, 2000, this.options.map.getDiv());

  wax.g.connector.call(this, opts);

  // lovely wax connector overwrites options so set them again
  // TODO: remove wax.connector here
   _.extend(this.options, opts);
  this.projector = new Projector(opts.map);
  this._addInteraction();
  this._checkTiles();
};

CartoDBLayer.Projector = Projector;

CartoDBLayer.prototype = new wax.g.connector();
_.extend(CartoDBLayer.prototype, CartoDBLayerCommon.prototype);

CartoDBLayer.prototype.setOpacity = function(opacity) {

  this._checkLayer();

  if (isNaN(opacity) || opacity > 1 || opacity < 0) {
    throw new Error(opacity + ' is not a valid value, should be in [0, 1] range');
  }
  this.opacity = this.options.opacity = opacity;
  for(var key in this.cache) {
    var img = this.cache[key];
    img.style.opacity = opacity;
    img.style.filter = "alpha(opacity=" + (opacity*100) + ");"

    //img.setAttribute("style","opacity: " + opacity + "; filter: alpha(opacity="+(opacity*100)+");");
  }

};

CartoDBLayer.prototype.setAttribution = function() {};

CartoDBLayer.prototype.getTile = function(coord, zoom, ownerDocument) {

  var self = this;

  this.options.added = true;

  var im = wax.g.connector.prototype.getTile.call(this, coord, zoom, ownerDocument);

  if (this.tiles == 0) {
    this.loading && this.loading();
    //this.trigger("loading");
  }

  this.tiles++;

  im.onload = im.onerror = function() {
    self.tiles--;
    if (self.tiles == 0) {
      self.finishLoading && self.finishLoading();
    }
  }

  return im;
}

CartoDBLayer.prototype._addInteraction = function () {
  var self = this;
  // add interaction
  if(this._interaction) {
    return;
  }
  this._interaction = wax.g.interaction()
    .map(this.options.map)
    .tilejson(this._tileJSON());
  this.setInteraction(true);
};

CartoDBLayer.prototype.clear = function () {
  if (this._interaction) {
    this._interaction.remove();
    delete this._interaction;
  }
  self.finishLoading && self.finishLoading();
};

CartoDBLayer.prototype.update = function () {
  var tilejson = this._tileJSON();
  // clear wax cache
  this.cache = {};
  // set new tiles to wax
  this.options.tiles = tilejson.tiles;
  this._interaction.tilejson(tilejson);

  this._checkTiles();

  // reload the tiles
  this.refreshView();
};

CartoDBLayer.prototype.refreshView = function() {
}

/**
 * Active or desactive interaction
 * @params {Boolean} Choose if wants interaction or not
 */
CartoDBLayer.prototype.setInteraction = function(enable) {
  var self = this;

  if (this._interaction) {
    if (enable) {
      this._interaction
        .on('on',function(o) {
          self._manageOnEvents(self.options.map, o);
        })
        .on('off', function(o) {
          self._manageOffEvents();
        });
    } else {
      this._interaction.off('on');
      this._interaction.off('off');
    }
  }
};

CartoDBLayer.prototype.setOptions = function (opts) {
  _.extend(this.options, opts);

  if (typeof opts != "object" || opts.length) {
    throw new Error(opts + ' options has to be an object');
  }

  if(opts.interactivity) {
    var i = opts.interactivity;
    this.options.interactivity = i.join ? i.join(','): i;
  }
  if(opts.opacity !== undefined) {
    this.setOpacity(this.options.opacity);
  }
  if(opts.interaction !== undefined) {
    this.setInteraction(this.options.interaction);
  }

  // Update tiles
  if(opts.query || opts.style || opts.tile_style || opts.interactivity) {
    this.update();
  }
}

CartoDBLayer.prototype._checkLayer = function() {
  if (!this.options.added) {
    throw new Error('the layer is not still added to the map');
  }
}
/**
 * Change query of the tiles
 * @params {str} New sql for the tiles
 * @params {Boolean}  Choose if the map fits to the sql results bounds (thanks to @fgblanch)
*/
CartoDBLayer.prototype.setQuery = function(sql) {

  this._checkLayer();

  /*if (fitToBounds)
    this.setBounds(sql)
    */

  // Set the new value to the layer options
  this.options.query = sql;
  this.update();
}

CartoDBLayer.prototype.isVisible = function() {
  return this.options.visible;
}

CartoDBLayer.prototype.setCartoCSS = function(style, version) {

  this._checkLayer();

  version = version || cdb.CARTOCSS_DEFAULT_VERSION;

  this.setOptions({
    tile_style: style,
    style_version: version
  });
}

/**
 * Change the query when clicks in a feature
 * @params { Boolean || String } New sql for the request
 */
CartoDBLayer.prototype.setInteractivity = function(fieldsArray) {

  this._checkLayer();

  if (!fieldsArray) {
    throw new Error('should specify fieldsArray');
  }

  // Set the new value to the layer options
  this.options.interactivity = fieldsArray.join ? fieldsArray.join(','): fieldsArray;
  // Update tiles
  this.update();
}

CartoDBLayer.prototype._findPos = function (map,o) {
  var curleft, cartop;
  curleft = curtop = 0;
  var obj = map.getDiv();
  do {
    curleft += obj.offsetLeft;
    curtop += obj.offsetTop;
  } while (obj = obj.offsetParent);
  return new google.maps.Point(
      (o.e.clientX || o.e.changedTouches[0].clientX) - curleft,
      (o.e.clientY || o.e.changedTouches[0].clientY) - curtop
  );
};

CartoDBLayer.prototype._manageOffEvents = function(){
  if (this.options.featureOut) {
    return this.options.featureOut && this.options.featureOut();
  }
};

CartoDBLayer.prototype._manageOnEvents = function(map,o) {
  var point  = this._findPos(map, o);
  var latlng = this.projector.pixelToLatLng(point);

  switch (o.e.type) {
    case 'mousemove':
      if (this.options.featureOver) {
        return this.options.featureOver(o.e,latlng, point, o.data);
      }
      break;

    case 'click':
    case 'touchend':
      if (this.options.featureClick) {
        this.options.featureClick(o.e,latlng, point, o.data);
      }
      break;
    default:
      break;
  }
}

cdb.geo.CartoDBLayerGMaps = CartoDBLayer;

/**
* gmaps cartodb layer
*/

var GMapsCartoDBLayerView = function(layerModel, gmapsMap) {
  var self = this;

  _.bindAll(this, 'featureOut', 'featureOver', 'featureClick');

  // CartoDB new attribution,
  // also we have the logo
  layerModel.attributes.attribution = "CartoDB attribution";

  var opts = _.clone(layerModel.attributes);

  opts.map =  gmapsMap;

  var // preserve the user's callbacks
  _featureOver  = opts.featureOver,
  _featureOut   = opts.featureOut,
  _featureClick = opts.featureClick;

  opts.featureOver  = function() {
    _featureOver  && _featureOver.apply(this, arguments);
    self.featureOver  && self.featureOver.apply(this, arguments);
  };

  opts.featureOut  = function() {
    _featureOut  && _featureOut.apply(this, arguments);
    self.featureOut  && self.featureOut.apply(this, arguments);
  };

  opts.featureClick  = function() {
    _featureClick  && _featureClick.apply(this, arguments);
    self.featureClick  && self.featureClick.apply(opts, arguments);
  };

  cdb.geo.CartoDBLayerGMaps.call(this, opts);
  cdb.geo.GMapsLayerView.call(this, layerModel, this, gmapsMap);
};

cdb.geo.GMapsCartoDBLayerView = GMapsCartoDBLayerView;

_.extend(
  GMapsCartoDBLayerView.prototype,
  cdb.geo.CartoDBLayerGMaps.prototype,
  cdb.geo.GMapsLayerView.prototype,
  {

  _update: function() {
    _.extend(this.options, this.model.attributes);

    this.update();

  },

  reload: function() {
    this.model.invalidate();
  },

  remove: function() {
    cdb.geo.GMapsLayerView.prototype.remove.call(this);
    this.clear();
  },

  featureOver: function(e, latlon, pixelPos, data) {
    // dont pass gmaps LatLng
    this.trigger('featureOver', e, [latlon.lat(), latlon.lng()], pixelPos, data);
  },

  featureOut: function(e) {
    this.trigger('featureOut', e);
  },

  featureClick: function(e, latlon, pixelPos, data) {
    // dont pass leaflet lat/lon
    this.trigger('featureClick', e, [latlon.lat(), latlon.lng()], pixelPos, data);
  },

  error: function(e) {
    //trigger the error form _checkTiles in the model
    this.model.trigger('error', e?e.error:'unknown error');
    this.model.trigger('tileError', e?e.error:'unknown error');
  },

  tilesOk: function(e) {
    this.model.trigger('tileOk');
  },

  loading: function() {
    this.trigger("loading");
  },

  finishLoading: function() {
    this.trigger("load");
  }

});

})();
<commit_msg>fixed problem in gmaps IE<commit_after>(function() {
// if google maps is not defined do not load the class
if(typeof(google) == "undefined" || typeof(google.maps) == "undefined")
  return;

// helper to get pixel position from latlon
var Projector = function(map) { this.setMap(map); };
Projector.prototype = new google.maps.OverlayView();
Projector.prototype.draw = function() {};
Projector.prototype.latLngToPixel = function(point) {
  var p = this.getProjection();
  if(p) {
    return p.fromLatLngToContainerPixel(point);
  }
  return [0, 0];
};
Projector.prototype.pixelToLatLng = function(point) {
  var p = this.getProjection();
  if(p) {
    return p.fromContainerPixelToLatLng(point);
  }
  return [0, 0];
  //return this.map.getProjection().fromPointToLatLng(point);
};

var CartoDBLayer = function(opts) {

  var default_options = {
    query:          "SELECT * FROM {{table_name}}",
    attribution:    "CartoDB",
    opacity:        1,
    auto_bound:     false,
    debug:          false,
    visible:        true,
    added:          false,
    loaded:         null,
    loading:        null,
    layer_order:    "top",
    tiler_domain:   "cartodb.com",
    tiler_port:     "80",
    tiler_protocol: "http",
    sql_domain:     "cartodb.com",
    sql_port:       "80",
    sql_protocol:   "http",
    subdomains:      null
  };

  this.options = _.defaults(opts, default_options);
  opts.tiles = this._tileJSON().tiles;

  // Set init
  this.tiles = 0;

  // Add CartoDB logo
  this._addWadus({left: 74, bottom:8}, 2000, this.options.map.getDiv());

  wax.g.connector.call(this, opts);

  // lovely wax connector overwrites options so set them again
  // TODO: remove wax.connector here
   _.extend(this.options, opts);
  this.projector = new Projector(opts.map);
  this._addInteraction();
  this._checkTiles();
};

CartoDBLayer.Projector = Projector;

CartoDBLayer.prototype = new wax.g.connector();
_.extend(CartoDBLayer.prototype, CartoDBLayerCommon.prototype);

CartoDBLayer.prototype.setOpacity = function(opacity) {

  this._checkLayer();

  if (isNaN(opacity) || opacity > 1 || opacity < 0) {
    throw new Error(opacity + ' is not a valid value, should be in [0, 1] range');
  }
  this.opacity = this.options.opacity = opacity;
  for(var key in this.cache) {
    var img = this.cache[key];
    img.style.opacity = opacity;
    img.style.filter = "alpha(opacity=" + (opacity*100) + ");"

    //img.setAttribute("style","opacity: " + opacity + "; filter: alpha(opacity="+(opacity*100)+");");
  }

};

CartoDBLayer.prototype.setAttribution = function() {};

CartoDBLayer.prototype.getTile = function(coord, zoom, ownerDocument) {

  var self = this;

  this.options.added = true;

  var im = wax.g.connector.prototype.getTile.call(this, coord, zoom, ownerDocument);

  if (this.tiles == 0) {
    this.loading && this.loading();
    //this.trigger("loading");
  }

  this.tiles++;

  im.onload = im.onerror = function() {
    self.tiles--;
    if (self.tiles == 0) {
      self.finishLoading && self.finishLoading();
    }
  }

  return im;
}

CartoDBLayer.prototype._addInteraction = function () {
  var self = this;
  // add interaction
  if(this._interaction) {
    return;
  }
  this._interaction = wax.g.interaction()
    .map(this.options.map)
    .tilejson(this._tileJSON());
  this.setInteraction(true);
};

CartoDBLayer.prototype.clear = function () {
  if (this._interaction) {
    this._interaction.remove();
    delete this._interaction;
  }
  self.finishLoading && self.finishLoading();
};

CartoDBLayer.prototype.update = function () {
  var tilejson = this._tileJSON();
  // clear wax cache
  this.cache = {};
  // set new tiles to wax
  this.options.tiles = tilejson.tiles;
  this._interaction.tilejson(tilejson);

  this._checkTiles();

  // reload the tiles
  this.refreshView();
};

CartoDBLayer.prototype.refreshView = function() {
}

/**
 * Active or desactive interaction
 * @params {Boolean} Choose if wants interaction or not
 */
CartoDBLayer.prototype.setInteraction = function(enable) {
  var self = this;

  if (this._interaction) {
    if (enable) {
      this._interaction
        .on('on',function(o) {
          self._manageOnEvents(self.options.map, o);
        })
        .on('off', function(o) {
          self._manageOffEvents();
        });
    } else {
      this._interaction.off('on');
      this._interaction.off('off');
    }
  }
};

CartoDBLayer.prototype.setOptions = function (opts) {
  _.extend(this.options, opts);

  if (typeof opts != "object" || opts.length) {
    throw new Error(opts + ' options has to be an object');
  }

  if(opts.interactivity) {
    var i = opts.interactivity;
    this.options.interactivity = i.join ? i.join(','): i;
  }
  if(opts.opacity !== undefined) {
    this.setOpacity(this.options.opacity);
  }
  if(opts.interaction !== undefined) {
    this.setInteraction(this.options.interaction);
  }

  // Update tiles
  if(opts.query || opts.style || opts.tile_style || opts.interactivity) {
    this.update();
  }
}

CartoDBLayer.prototype._checkLayer = function() {
  if (!this.options.added) {
    throw new Error('the layer is not still added to the map');
  }
}
/**
 * Change query of the tiles
 * @params {str} New sql for the tiles
 * @params {Boolean}  Choose if the map fits to the sql results bounds (thanks to @fgblanch)
*/
CartoDBLayer.prototype.setQuery = function(sql) {

  this._checkLayer();

  /*if (fitToBounds)
    this.setBounds(sql)
    */

  // Set the new value to the layer options
  this.options.query = sql;
  this.update();
}

CartoDBLayer.prototype.isVisible = function() {
  return this.options.visible;
}

CartoDBLayer.prototype.setCartoCSS = function(style, version) {

  this._checkLayer();

  version = version || cdb.CARTOCSS_DEFAULT_VERSION;

  this.setOptions({
    tile_style: style,
    style_version: version
  });
}

/**
 * Change the query when clicks in a feature
 * @params { Boolean || String } New sql for the request
 */
CartoDBLayer.prototype.setInteractivity = function(fieldsArray) {

  this._checkLayer();

  if (!fieldsArray) {
    throw new Error('should specify fieldsArray');
  }

  // Set the new value to the layer options
  this.options.interactivity = fieldsArray.join ? fieldsArray.join(','): fieldsArray;
  // Update tiles
  this.update();
}

CartoDBLayer.prototype._findPos = function (map,o) {
  var curleft, cartop;
  curleft = curtop = 0;
  var obj = map.getDiv();
  do {
    curleft += obj.offsetLeft;
    curtop += obj.offsetTop;
  } while (obj = obj.offsetParent);
  return new google.maps.Point(
      (o.e.clientX || o.e.changedTouches[0].clientX) - curleft,
      (o.e.clientY || o.e.changedTouches[0].clientY) - curtop
  );
};

CartoDBLayer.prototype._manageOffEvents = function(){
  if (this.options.featureOut) {
    return this.options.featureOut && this.options.featureOut();
  }
};

CartoDBLayer.prototype._manageOnEvents = function(map,o) {
  var point  = this._findPos(map, o);
  var latlng = this.projector.pixelToLatLng(point);

  switch (o.e.type) {
    case 'mousemove':
      if (this.options.featureOver) {
        return this.options.featureOver(o.e,latlng, point, o.data);
      }
      break;

    case 'click':
    case 'touchend':
      if (this.options.featureClick) {
        this.options.featureClick(o.e,latlng, point, o.data);
      }
      break;
    default:
      break;
  }
}

cdb.geo.CartoDBLayerGMaps = CartoDBLayer;

/**
* gmaps cartodb layer
*/

var GMapsCartoDBLayerView = function(layerModel, gmapsMap) {
  var self = this;

  _.bindAll(this, 'featureOut', 'featureOver', 'featureClick');

  // CartoDB new attribution,
  // also we have the logo
  layerModel.attributes.attribution = "CartoDB attribution";

  var opts = _.clone(layerModel.attributes);

  opts.map =  gmapsMap;

  var // preserve the user's callbacks
  _featureOver  = opts.featureOver,
  _featureOut   = opts.featureOut,
  _featureClick = opts.featureClick;

  opts.featureOver  = function() {
    _featureOver  && _featureOver.apply(this, arguments);
    self.featureOver  && self.featureOver.apply(this, arguments);
  };

  opts.featureOut  = function() {
    _featureOut  && _featureOut.apply(this, arguments);
    self.featureOut  && self.featureOut.apply(this, arguments);
  };

  opts.featureClick  = function() {
    _featureClick  && _featureClick.apply(this, arguments);
    self.featureClick  && self.featureClick.apply(opts, arguments);
  };

  cdb.geo.CartoDBLayerGMaps.call(this, opts);
  cdb.geo.GMapsLayerView.call(this, layerModel, this, gmapsMap);
};

cdb.geo.GMapsCartoDBLayerView = GMapsCartoDBLayerView;

_.extend(
  GMapsCartoDBLayerView.prototype,
  cdb.geo.CartoDBLayerGMaps.prototype,
  cdb.geo.GMapsLayerView.prototype,
  {

  _update: function() {
    _.extend(this.options, this.model.attributes);

    this.update();

  },

  reload: function() {
    this.model.invalidate();
  },

  remove: function() {
    cdb.geo.GMapsLayerView.prototype.remove.call(this);
    this.clear();
  },

  featureOver: function(e, latlon, pixelPos, data) {
    // dont pass gmaps LatLng
    this.trigger('featureOver', e, [latlon.lat(), latlon.lng()], pixelPos, data);
  },

  featureOut: function(e) {
    this.trigger('featureOut', e);
  },

  featureClick: function(e, latlon, pixelPos, data) {
    // dont pass leaflet lat/lon
    this.trigger('featureClick', e, [latlon.lat(), latlon.lng()], pixelPos, data);
  },

  error: function(e) {
    if(this.model) {
      //trigger the error form _checkTiles in the model
      this.model.trigger('error', e?e.error:'unknown error');
      this.model.trigger('tileError', e?e.error:'unknown error');
    }
  },

  tilesOk: function(e) {
    this.model.trigger('tileOk');
  },

  loading: function() {
    this.trigger("loading");
  },

  finishLoading: function() {
    this.trigger("load");
  }

});

})();
<|endoftext|>