Rails - 搞清楚javascript配置 [英] Rails - figuring out the javascript config

查看:86
本文介绍了Rails - 搞清楚javascript配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我尝试过使用gmaps4rails,但放弃了,因为我已经努力了4年了解如何在我的Rails应用程序中使用Google地图。太难了。我在SO上找到了一个解决方案,除了我无法指定缩放级别外,其他解决方案都有效。但是,在制作过程中,我所有其他的javascript都无法使用。解决方案是移动:

 <%= javascript_include_tag'application','data-turbolinks-track': '重新加载'%> 

移出头标记并放在身体标记的底部。



在生产模式下,这可以让我所有其他js文件像开发环境中一样运行,但是现在地图根本不会渲染。



是否有解决方案:


  1. 允许我使用我的javascript文件谷歌地图js文件) - 我认为这是通过将JavaScript包含标签放在主体的最后而不是头部来实现的。


  2. 允许我呈现生产中的谷歌地图?如果我将javascript include标记移回头部,我可以渲染地图,但其余的js文件不起作用(仅在生产环境中)。


  3. 允许我在地图上指定缩放级别?

  4. 我试图寻求帮助此处这里(以及本主板上的其他时间)。我还没有设法找到帮助。



    在我的address.js中,我有:

     函数initMap (){
    var map = new google.maps.Map(document.getElementById('map'),{
    zoom:5
    });
    var bounds = new google.maps.LatLngBounds();
    // var opts = {
    // zoom:10,
    // max_zoom:16
    //}

    var n = addresses.length ;
    for(var i = 0; i< n; i ++){
    var lat = addresses [i] .latitude;
    var lng =地址[i] .longitude;
    if(lat == null || lng == null){
    console.log(addresses [i] .name +does not have coordinates);
    } else {
    var address = new google.maps.Marker({
    position:{lat:parseFloat(lat),lng:parseFloat(lng)},
    title:地址[i] .name,
    map:map //,
    // zoom:8
    });
    bounds.extend(address.position);
    }
    }
    map.fitBounds(bounds);
    }

    正如我在



      initMap不是函数

    我标记了所有相关帖子,提出了该链接帖子中的解决方案,以及我使用这些解决方案解决问题的结果。

    关于地图上的缩放级别,这篇文章解释了这个问题可归因于js要求一个包含每个地址的地图。不管怎样,我都会强制缩放级别成为最放大的级别,而不管我尝试指定的级别。所以有两个问题,第一个是如何去除强制最放大级别的位,以便我可以设置将被确认的缩放级别,第二个是表示放大方式是否有一些变化级别,因为如此多的答案(包括那些链接在我的帖子中)建议使用setZoom而不是zoom:5。我无法找到解决方案。



    正如我在这篇文章,如果我在头部有javascript include标签,那么js文件(谷歌地图除外)在生产中不起作用。经过长时间,昂贵的codementor会议之后,我才得出这个解决方案。我无法承受另一场会议,以了解如何解决此解决方案所造成的问题。我也没有解释为什么这种改变是必要的。导轨指南建议将它包括在内,所以我不明白为什么大多数情况下,将它移动到主体标签的末尾是一种解决方案,可让js在生产环境中工作。这打破了地址js,所以它不是正确的解决方案。

    在我的config.rb中,我有

      config / initializers / assets.rb 

    #修改此文件时一定要重新启动服务器。
    #您的资产版本,如果您想要过期所有资产,请更改此值。
    Rails.application.config.assets.version ='1.0'

    #将其他资产添加到资产加载路径
    #Rails.application.config.assets.paths< < Emoji.images_path

    #预编译其他资产。
    #application.js,application.css以及app / assets文件夹中的所有非JS / CSS都已添加。
    #Rails.application.config.assets.precompile + =%w(search.js)
    config / production.rb

    #如果预编译不要回退到资产管道资产被遗漏。
    config.assets.compile = false

    我已经尝试了每个发布在(主要是来自其他人发表在这个论坛上的帖子),我很想学习解决这个问题的原理(这样我就可以开始学会思考轨道需要我的方式了),我很困惑为什么这么困难以及为什么这么少的关于配置应用程序在任何文本中的生产中工作的问题显然存在一个需要解决方案的问题(我已经梳理了100多个关于此主题的其他帖子,但无法找到一个原则性的答案)或解决方案。



    如果它有什么不同,我的生产环境是在heroku上。任何建议,对于相关的原则都是非常重要的赞赏 - 如果直接回答不立即显现。



    采取R_G的建议



    我更改了我的address.js文件以包含新的第一行和新的la st line。现在这个文件有:

    $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ map = new google.maps.Map(document.getElementById('map'),{
    zoom:5
    });
    var bounds = new google.maps.LatLngBounds();
    // var opts = {
    // zoom:10,
    // max_zoom:16
    //}

    var n = addresses.length;
    for(var i = 0; i< n; i ++){
    var lat = addresses [i] .latitude;
    var lng = addresses [i] .longitude;
    if(lat == null || lng == null){
    console.log(addresses [i] .name +没有坐标);
    } else {
    var address = new google.maps.Marker({
    position:{lat:parseFloat(lat),lng:parseFloat(lng)},
    title:addresses [i] .name,
    map:map //,
    // zoom:8
    });
    bounds.extend(address.position);
    }
    }
    map .fitBounds(bounds);
    }
    })();

    当我启动服务器并尝试渲染页面时,地图仍然不渲染(仅仅是一个它应该是空的空白空间)。在Chrome检查器中没有显示控制台错误(就像我没有使用R_G建议的第一行和最后一行一样)。
    $ b RESPONSE TO工程师DAVE
    针对您的问题:

    Q1:您的生产资产是否被预编译?



    不 - 原因是我的production.rb注释告诉我不要。请参阅:

     #如果预编译的资产被遗漏,不要回退到资产管道。 
    config.assets.compile = true

    #`config.assets.precompile`和`config.assets.version`已移至config / initializers / assets.rb

    我理解这些说明意味着assets.rb处理预编译,因此不再需要预编译生产资产。我上面复制的第一行指令告诉我不要回退到资产管道,所以我不确定你期望看到什么不同。



    在asset.rb,注释说:

     #application.js,application.css和应用程序中的所有非JS / CSS / assets文件夹已添加。#如果预编译的资源丢失,请不要回退到资产管道。 

    我明白这意味着application.js中列出的所有东西都已被处理,因此不需要进一步重新编译步骤。我明白(从过去几年来解决这个问题,在编译时加倍是导致一组单独问题的原因)。



    我的address.js文件在我的application.js文件(通过require树)中列出,所以它应该由assets.rb使用的任何进程处理。



    Q2。您是否需要application.js中的树



    是的。我是。



    给你的评论:另外,如果你不需要application.js中的整个JS文件,那么你已经标记了用于资源预编译的文件。 rb,例如address.js,将被预编译,但不会被加载。



    我的application.js包含:

      // = require jquery 
    // =需要jquery_ujs
    // =需要turbolinks
    // =需要jquery-fileupload / vendor / jquery.ui.widget
    // =需要jquery-fileupload / jquery .iframe-transport
    // =需要jquery-fileupload / jquery.fileupload
    // =需要bootstrap-sprockets
    // =需要时刻
    // = require bootstrap-datetimepicker
    // =需要采集者
    //需要下划线
    //需要gmaps / google
    // =需要markerclusterer
    // =需要cocoon
    / / =需要电缆
    // = require_tree。

    我需要这棵树。 Address.js位于我的app / assets / javascripts文件夹中,因此它应该被application.js中列表末尾的require_tree行选取。



    我是不知道我了解你的评论。有没有建议我可以试着做到这一点?您的建议是忽略assets.rb和production.rb设置中的说明吗?



    'precompiled'和'loaded'之间的区别是什么?



    工程师对R_G建议的评论



    EngineerDave建议将此帖作为潜在解决方案。这篇文章建议:


    1. 将javascript include标记移动到我的身体标记的末尾(我已完成,谷歌地图不再起作用,但其他文件中的hide / show js现在无法正常工作)。

    2. 使用下面这行代码: / p>

      document.addEventListener(DOMContentLoaded,function(event){
      // do work
      });


    这篇文章提出了一个简单的实现该行的方法,如下所示:


    一个实际的工作普通的javascript实现在这里,如果有人
    想要代码,他们可以放在:
    stackoverflow.com/questions/9899372/... - jfriend00 14年14月13日在7:58


    该链接,建议:

     <脚本> 
    //自动执行函数
    (函数(){
    //您的页面初始化代码
    // DOM将在此处可用

    })();
    < / script>

    我在address.js中的当前代码从这一行开始:

     函数initMap(){

    这个帖子中的建议,我尝试用下面的代码替换那行:

     (function(){
    function initMap() {
    //然后继续我的address.js文件的其余部分
    })();

    当我保存并尝试它时,我得到的结果与我尝试R_G的第一个建议时相同。没有地图。没有控制台错误显示在Chrome检查器中。



    DOWNVOTE

    不明白在这个问题上反对的原因。我一直在努力尝试学习如何使用JavaScript来处理rails。我在codementor.io / upwork上花了数千美元,还有其他一些网站试图支付专业帮助来学习。我参加过我所有城市的聚会,并有机会在不同的城市尝试他们的尝试。我还没有找到一个能够解决这个问题的人。 4年以上,我仍然试图解决这个问题。什么是拒绝投票的理由。它并没有给我任何见识,为什么这个论坛不是寻求帮助的合适地点。我没有选择的选择。我只是没有更多的预算浪费在codementor.io上。反对票只会让我的分数降低,因为我可以在这个论坛上发起另一个奖励,试图找到一些有助于解决这个问题的信息。如果你对如何更好地提出这个问题有所建设性的反馈,或者做必要的研究来找到答案 - 那些东西将感激地感激。祝你有个愉快的一天。



    对于其他人,谢谢你帮助我。

    布朗尼的建议

    非常感谢您抽出宝贵时间回购。看到别人把这件事放在外面是很有帮助的。这就是说,这不适合我。我不得不调整你的一些方法来摆脱这些对我造成的一些错误。我列出了我如何整合您的建议以及它在下面给出的错误:

    Application.html.erb



    更改:


    1. 我将javascript include标记移回到标记


    2. 在js包含标签之上,我放置了google源代码链接。我在下面的评论中显示了您建议的链接,以及我在其下面使用的链接。我不得不改变链接,因为我得到一个错误,说你的链接没有API键。



       <%= csrf_meta_tags%> 
      <%= favicon_link_tag%>
      <! - < script src =https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false>< / script> - >
      < script src =https://maps.googleapis.com/maps/api/js?key=<%= ENV [GOOGLE_MAPS_API_KEY]%>async defer>< / script>

      <%= stylesheet_link_tag'application',media:'all','data-turbolinks-track':'reload'%>
      <! - 最新的编译和缩小CSS - >
      <%= stylesheet_link_tag href =https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css%>

      <! - 可选主题 - >
      <%= stylesheet_link_tag href =https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min.css%>
      <%= javascript_include_tag'application','data-turbolinks-track':'reload'%>


    app / assets / javascripts / initialise.js



    我制作了一个新文件 - 与您的文件一样。



    pre $ lt; code> function initialize(){
    var losAngeles = new google.maps.LatLng(34.0500,-118.2500);
    var pasadena = new google.maps.LatLng(34.14778,-118.14452);
    var mapOptions = {
    zoom:10,
    center:losAngeles,
    disableDefaultUI:true,
    mapTypeControlOptions:google.maps.MapTypeId.SATELLITE
    } ;
    map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
    }

    google.maps.event.addDomListener(window,'load',initialize);

    当前错误指向此文件的最后一行。

    我从你的评论中不理解的一件事是,你认为这个文件不在资产管道之中。我不明白,因为你的application.js有require_tree,我的理解是app / assets / javascripts中的所有内容都包含在管道中。



    我的视图现在和你一样:

     < div id =map-canvas>< / div> 

    当我保存所有这些并尝试它时,我收到一个错误消息:

      Uncaught ReferenceError:google未定义
    在initialize.self-f919dc6 ... .js?body = 1:13
    (anonymous)@ initialize.self-f919dc6 ... .js?body = 1:13

    一个空白的空白而不是一张地图。



    更大的问题



    I推这到heroku并尝试生产版本。现在,隐藏&显示基于其他表单字段的表单不起作用。这是导致将javascript include标签放在body标签而不是head标签的原始问题。

    这个js位于名为app / assets的文件中/javascripts/stance/commercial.js

      jQuery(document).ready(function(){
    jQuery(' ('click',function(){
    if(jQuery(this).val()=='true'){$ b $('name'='organization [commercial_attributes] [standard_financial_split]]') b'jQuery('#commercial_standard_financial_split_content')。removeClass('hidden');
    } else {
    jQuery('#commercial_standard_financial_split_content')。removeClass('hidden')。addClass('hidden');
    }
    });

    });

    当javascript include标签移动到body标签的末尾时,现在它回到了头标记 - 它不起作用。

    解决方案

    编辑:查看最新的更新以获取更详细的解释,但我刚刚看到最可能出现的错误。如果你遵循我的建议,它肯定会有所帮助。我假设你只粘贴了你的代码的一个功能,而不是你的整个文件。在JavaScript中确保整个页面在您的代码开始运行之前已经加载(通常)非常重要。这是我推荐的function(){...}的目的。等待文档在脚本执行开始前加载。没有这些,你可能会在脚本中看到虚假的错误,比如initMap不是函数。按照我的建议,看看是否有帮助。






    您可能已经在做这件事了,所以让我知道这是否属实但是...

    如果您的结果根据脚本中的位置而有所不同,我认为您会污染全局名称空间并因此受到冲突变量的影响。将所有代码包装起来以使其结构本地化并且不会影响全局更安全。

    纯JavaScript会有这样的模式:

    $ p $ ;(function ){
    //文档在这里准备好
    })();

    我使用jQuery,所以我这样做:

     ; $(函数($,window,document){
    //文档准备在这里
    }(window.jQuery,window,document) );

    具体如何做这取决于您自己的模式,但目标是不污染全球环境。



    嘿,至少值得一试。






    更新:既然你问过了,我向你介绍了第一个建议,让我来为你解析。使用的代码是:

     ;(function(){
    //文档在这里准备好
    })();

    用当前的代码替换// Document is ready here。如果您有多个包含当前代码的文件,请为每个文件执行相同的操作。



    第一个分号仅用于终止前面的代码,以防忘记终止代码。分号后的括号是本地隔离的关键。它与最后一行中的第一个括号配对。您在这些括号内定义的任何变量或函数都将与它们之外的任何东西隔离。最后一行的最后两个成对括号将所有代码作为函数执行,因此实例化您的内部代码。没有这些,你的代码将无法访问。

    I have been struggling for 4 years to figure out how I can use google maps in my Rails app.

    I've tried to use gmaps4rails but given up because it's too hard. I managed to find a solution on SO, which worked except that i couldn't specify a zoom level. However, in production, all of my other javascripts didn't work. The solution for that was to move the:

    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    

    out of the head tag and to the bottom of the body tag.

    That works to let all of my other js files operate as they do in the development environment, when in production mode, however, now the map won't render at all.

    Is there a solution which:

    1. allows me to use my javascript files (other than the google maps js file)- which I think is achieved by having the javascript include tag at the end of the body instead of the head

    2. allows me to render a google map in production? If I move the javascript include tag back to the head I can render the map, but the rest of my js files don't work (in production only).

    3. allows me to specify a zoom level on my map?

    I have tried to ask for help here, here and here (and a million other times on this board). I haven't managed to find help yet.

    In my address.js, I have:

    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 5
      });
      var bounds = new google.maps.LatLngBounds();
      // var opts = {
      //   zoom: 10,
      //   max_zoom: 16
      // }
    
      var n = addresses.length;
      for (var i = 0; i < n; i++) {
        var lat = addresses[i].latitude;
        var lng = addresses[i].longitude;
        if (lat == null || lng ==null){
          console.log(addresses[i].name + " doesn't have coordinates");
        }else {
          var address = new google.maps.Marker({
            position: {lat: parseFloat(lat), lng: parseFloat(lng)},
            title: addresses[i].name,
            map: map //,
    //        zoom: 8
          });
          bounds.extend(address.position);
        }
      }
      map.fitBounds(bounds);
    }
    

    As I outlined in this post, I get an error that says:

    initMap is not a function
    

    I've tagged all the relevant posts that suggest solutions in that linked post, together with the results of my efforts to use those solutions to solve my problem.

    In relation to the zoom level on the map, the answer in this post explained the problem as being attributable to the js asking for a map with each address in it. That somehow forces the zoom level to be the most zoomed in, regardless of the level I try to specify. So there are 2 issues, the first is how to remove the bit that forces the most zoomed in level so that I can set a zoom level that will be acknowledged and the second is whether there has been some change in the way to express the zoom level, because so many answers on SO (including those linked in my post) suggest using "setZoom" instead of "zoom: 5". I can't find a solution that worked.

    As I outlined in this post, the js files (except for google maps) don't work in production if I have the javascript include tag in the head. I only arrived at this solution after a long, expensive session on codementor. I can't afford another session to find out how to solve the problems that this solution has created. I also didn't get an explanation as to the fundamental reason why this change is necessary. The rails guides suggest including it there so I don't understand why, for the most part, moving it to the end of the body tag is a solution that gets the js to work in the production environment. This breaks the address js though, so it isn't the right solution

    In my config.rb I have

    config/initializers/assets.rb
    
    # Be sure to restart your server when you modify this file.
    # Version of your assets, change this if you want to expire all your assets.
    Rails.application.config.assets.version = '1.0'
    
    # Add additional assets to the asset load path
    # Rails.application.config.assets.paths << Emoji.images_path
    
    # Precompile additional assets.
    # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
    # Rails.application.config.assets.precompile += %w( search.js )
    config/production.rb
    
      # Do not fallback to assets pipeline if a precompiled asset is missed.
      config.assets.compile = false
    

    I have tried each of the solutions posted in the linked posts (which are mostly from others who have posted on this board. I would love to learn the principle involved in figuring this out (so that I can begin to learn to think the way that rails wants me to). I'm baffled by why this is so difficult and why so little is written about configuring apps to work in production in any of the texts. There is clearly a problem that needs a solution (I have combed through 100s of other posts on this topic, but cannot find a principled answer) or a solution that works.

    If it makes any difference, my production environment is on heroku. Any advice, for principles that are relevant would be very much appreciated - if a direct answer is not immediately apparent.

    TAKING R_G'S SUGGESTION

    I changed my address.js file to include a new first line and a new last line. That file now has:

    ;(function ready() {
    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 5
      });
      var bounds = new google.maps.LatLngBounds();
      // var opts = {
      //   zoom: 10,
      //   max_zoom: 16
      // }
    
      var n = addresses.length;
      for (var i = 0; i < n; i++) {
        var lat = addresses[i].latitude;
        var lng = addresses[i].longitude;
        if (lat == null || lng ==null){
          console.log(addresses[i].name + " doesn't have coordinates");
        }else {
          var address = new google.maps.Marker({
            position: {lat: parseFloat(lat), lng: parseFloat(lng)},
            title: addresses[i].name,
            map: map //,
    //        zoom: 8
          });
          bounds.extend(address.position);
        }
      }
      map.fitBounds(bounds);
    }
    })();
    

    When I start the server and try to render the page, the map still does not render (just an empty white space where it should be). There are no console errors showing in the chrome inspector (just as there are not when I do not use the first and last lines suggested by R_G).

    RESPONSE TO ENGINEER DAVE In response to your questions:

    Q1: Are your production assets being precompiled?

    No - the reason for that is that my production.rb notes tell me not to. See here:

    # Do not fallback to assets pipeline if a precompiled asset is missed.
      config.assets.compile = true
    
      # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
    

    I understand these notes to mean that assets.rb handles the precompilation, so there is no longer a need to precompile production assets. The first line of the instructions that I copied above tells me not to fallback to the assets pipeline so I'm not sure what you're expecting to see differently.

    In asset.rb, the notes say:

    # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.# Do not fallback to assets pipeline if a precompiled asset is missed.
    

    I understand this to mean everything listed in application.js is already handled so there is no need for further recompilation steps. I understand (from previous attempts over the years to solve this problem that doubling up on the compilation is a cause of a separate set of problems).

    My address.js file is listed in my application.js file (via the require tree), so it should be dealt with by whatever the process that assets.rb uses.

    Q2. Are you requiring the tree in application.js

    Yes. I am.

    To your comment: "Also if you're not requiring the whole JS tree of files in application.js then the files you have flagged for pre-compilation in assets.rb, e.g. address.js, will get precompiled but will not be loaded."

    My application.js has:

    //= require jquery
    //= require jquery_ujs
    //= require turbolinks
    //= require jquery-fileupload/vendor/jquery.ui.widget
    //= require jquery-fileupload/jquery.iframe-transport
    //= require jquery-fileupload/jquery.fileupload
    //= require bootstrap-sprockets
    //= require moment
    //= require bootstrap-datetimepicker
    //= require pickers
    // require underscore
    // require gmaps/google
    //= require markerclusterer
    //= require cocoon
    //= require cable
    //= require_tree .
    

    I am requiring the tree. Address.js is in my app/assets/javascripts folder so it should be picked up by the require_tree line at the end of the list in application.js

    I'm not sure I've understood any of your comment. Is there a suggestion that I could try to get this working? Is your suggestion to ignore the instructions in the assets.rb and production.rb setup?

    What is the difference between 'precompiled' and 'loaded'? I'll try to do some research to understand what that means now.

    ENGINEERDAVE'S COMMENT ON R_G'S SUGGESTION

    EngineerDave suggests referring to this post as a potential solution. This post suggests:

    1. moving the javascript include tag to the end of my body tag (which I have done, with the effect that the google map no longer works but the hide /show js in the other file that wasn't working now does work).

    2. using this line:

      document.addEventListener("DOMContentLoaded", function(event) { //do work });

    That post goes on to suggest a simpler implementation of that line, as:

    An actual working plain javascript implementation here if someone wants code they can just drop in: stackoverflow.com/questions/9899372/… – jfriend00 Dec 13 '14 at 7:58

    That link, suggests:

    <script>
    // self executing function here
    (function() {
       // your page initialization code here
       // the DOM will be available here
    
    })();
    </script>
    

    My current code in address.js begins with this line:

    function initMap() {
    

    Taking the suggestion in this post, I try replacing that line with:

    (function() {
      function initMap() {
       //then continue with the rest of my address.js file
    })();
    

    When I save this and try it, I get the same outcome as when I tried R_G's first suggestion. No map. No console errors showing in the chrome inspector.

    THE DOWNVOTE

    I don't understand the reason for the down vote on this question. I have been struggling for years to try to learn how to work with rails with javascript. I have spent thousands of dollars on codementor.io/ upwork and a bunch of the other sites trying to pay for professional help to learn this. I've been to every meetup in my city and make a point to try them in different cities when I have the opportunity to do so. I haven't found a person who has been able to figure this out. 4+ years and I'm still trying to solve this. What's the reason to down vote this. It doesn't give me any insight as to why this forum is not the right place to seek help. I'm out of options for alternatives. I just don't have any more budget to waste on codementor.io. The down vote only costs me points which slows me down from being able to start another bounty on this forum to try and find some information that will help to solve this problem. If you have constructive feedback on how better to ask this question or do the research necessary to find the answer - either of those things would be gratefully appreciated. Have a nice day.

    To everyone else, thank you for trying to help me.

    BRENZY'S SUGGESTION

    Thank you so much for taking the time to make the repo. It's so helpful to see someone else lay this out. That said, this doesnt work for me. I had to adapt some of your approach to get rid of some of the errors this made for me. I've set out how I incorporated your suggestion and the error it gives below:

    Application.html.erb

    Changes:

    1. I moved the javascript include tag back to the head tag

    2. Above the js include tag, I put the google source link. I've shown the link you suggested in comment below, and the link I used beneath it. I had to change the link because I got an error saying no API keys using your link.

      <%= csrf_meta_tags %>
      <%= favicon_link_tag %>
      <!-- <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script> -->
      <script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAPS_API_KEY"] %>"async defer></script>
      
      <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
      <!-- Latest compiled and minified CSS -->
      <%= stylesheet_link_tag  href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css" %>
      
      <!-- Optional theme -->
      <%= stylesheet_link_tag href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min.css" %>
      <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
      

    app/assets/javascripts/initialise.js

    I made a new file - like yours.

    function initialize() {
      var losAngeles = new google.maps.LatLng(34.0500, -118.2500);
      var pasadena = new google.maps.LatLng(34.14778, -118.14452);
      var mapOptions = {
        zoom: 10,
        center: losAngeles,
        disableDefaultUI: true,
        mapTypeControlOptions: google.maps.MapTypeId.SATELLITE
      };
      map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    }
    
    google.maps.event.addDomListener(window, 'load', initialize);
    

    The current error is pointing at the last line of this file.

    One thing I don't understand from your commentary is that you think this file is outside of the asset pipeline. I don't understand that because your application.js has require_tree, which I understand to mean that everything in app/assets/javascripts gets included in the pipeline.

    My view is now the same as yours:

    <div id="map-canvas"></div>
    

    When I save all of this and try it, I get an error that says:

    Uncaught ReferenceError: google is not defined
        at initialize.self-f919dc6….js?body=1:13
    (anonymous) @ initialize.self-f919dc6….js?body=1:13
    

    There is just a blank white space instead of a map.

    THE BIGGER PROBLEM

    I pushed this to heroku and tried the production version. Now, the js that hides & shows form fields based on other form selections doesnt work. This was the original problem that led to putting the javascript include tag at the end of the body instead of the head tag.

    That js is in a file called app/assets/javascripts/stance/commercial.js

    jQuery(document).ready(function() {
       jQuery('[name="organisation[commercial_attributes][standard_financial_split]"]').on('click', function() {
          if (jQuery(this).val() == 'true' ) {
              jQuery('#commercial_standard_financial_split_content').removeClass('hidden');
          } else {
              jQuery('#commercial_standard_financial_split_content').removeClass('hidden').addClass('hidden');
          }
       });
    
    });
    

    This did work when the javascript include tag was moved to the end of the body tag. Now that it's back in the head tag - it doesnt work.

    解决方案

    EDIT: See update at the end for a more detailed explanation, but I just saw what is your most likely error. If you follow my recommendation, it should certainly help. I assumed that you only pasted in one function of your code, not your entire file. It is (most often) important in JavaScript to ensure that the entire page has loaded before your code begins to run. That is the purpose of the "function(){...}" that I recommended. It waits until the document is loaded before script execution starts. Without that, you will likely see spurious errors in your scripts, like "initMap is not a function". Follow my recommendation and see if that helps.


    You could already be doing this, so let me know if that is true but...

    If your results vary according to placement within the scripts, my thought would be that you are polluting the global namespace and suffering conflicting variables as a result. It's much safer to wrap all your code such that it's structure is local and does not impact the global.

    Pure JavaScript would have this pattern:

    ;(function() {
        // Document is ready here
    })();
    

    I use jQuery, and so I do it this way:

    ;$(function ($, window, document) {
        // Document ready here
    }(window.jQuery, window, document));
    

    Exactly how you want to do this depends upon your own pattern, but the goal is to not pollute the global environment.

    Hey, it's at least worth a shot.


    UPDATE: Since you asked and I referred you to the first suggestion, let me parse that out for you. The code to use is:

    ;(function() {
        // Document is ready here
    })();
    

    Replace "// Document is ready here" with your current code. If you have multiple files containing your current code, do the same for each.

    The first semicolon is just there to terminate any preceding code, in case they forgot to terminate it. The parenthesis after the semicolon is the key to the local isolation. It pairs with the first parenthesis in the last line. Any variables or functions that you define within those parenthesis will be isolated from anything outside of them. The last two paired parenthesis on the last line executes all of the code as a function, therefore instantiating your internal code. Without that, your code would be inaccessible.

    这篇关于Rails - 搞清楚javascript配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆