0

I am trying to add JQuery functionality to my Rails application; however, it is not working. I am using JQuery draggable to move images around the screen. I have it working in a stand alone html file but I'm having a lot of difficulty adding it to my Rails application. This is the stand alone file:

<!DOCTYPE html>
<html>
<head>
  <title>City</title>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="js/jquery-ui-1.10.4/themes/base/jquery-ui.css">
  <script type="text/javascript" src="js/jquery-ui-1.10.4/jquery-1.10.2.js"></script>
  <script type="text/javascript" src="js/jquery-ui-1.10.4/ui/jquery-ui.js"></script>

  <style type="text/css">

  h1, h3
  {
    text-align: center; 
    margin: 0px;
  }

  /* style the list to maximize the droppable hitarea */
  #canvas  
  {
    width: 600px;
    height: 600px;
    border: 1px solid black;
    margin: 0px auto;
    overflow: hidden;
  }
  /*#canvas ol { margin: 0; padding: 1em 0 1em 3em; }*/
  /*li { list-style: none;}*/
  .canvas-area 
  {
    width: 600px;
    height: 600px;
  }

  /* map background */
/*  img {
      position: relative;
      left: 50%;
      top: 50%;
  }*/

  /* draggable icons */
  .draggable 
  { 
    background: transparent url('images/transparent.png') repeat center top;
    width: 40px; 
    height: 40px; 
    padding: 5px; 
    float: left; 
    margin: 0 10px 10px 0; 
    font-size: .9em; 
    border: hidden;
    /*position: absolute;*/
  }
  #draggable
  {
    width: 40px;
    height: 40px;
  }
  div img 
  {
    margin: 0px auto;
    position: relative;
    top: 0px;
    left: 0px;
    width: 40px;
    height: 40px;
  }

  .arrow img
  {
    width: 200px;
    height: 200px;
  }
  .arrow
  {
    width: 200px;
    height: 200px;
    border: 1px solid black;
  }
  .commercial100 img
  {
    width: 100px;
    height: 100px;
  }
  .commercial100
  {
    width: 100px;
    height: 100px;
  }

  #building img
  {
    height: 150px;
  }

  </style>

  <script>

    // jquery ui script for snapping to grid
    $(function() {
      $( ".draggable" ).draggable({ grid: [10,10] });
      $( "#draggable4" ).draggable({ grid: [ 20, 20 ], snap: true });
    });

  </script>
</head>
<body>
<div class="content">

  <!-- Canvas for building the city -->
  <h1>Mock view of my city</h1>
  <h3>600 x 600</h3>
  <div id="canvas">

    <div id="ignoreThis" class="ui-widget-content canvas-area">

      <p class="placeholder">Add your items here</p>

      <div id="arrowSvg" class="draggable ui-widget-content arrow">
        <img src="images/arrow.svg" alt="house" type="image/svg+xml" /> SVG (200px x 200px)
      </div>

      <div id="arrowPng" class="draggable ui-widget-content arrow">
        <img src="images/arrow.png" alt="house"> PNG (200px x 200px) 
      </div>

      <div id="building" class="draggable ui-widget-content commercial100">
        <img src="images/building.png" alt="building" />
      </div>

      <div id="factory" class="draggable ui-widget-content commercial100" >
        <img src="images/factory.png" alt="factory" />
      </div>

      <div id="ferry" class="draggable ui-widget-content commercial100" >
        <img src="images/ferry.png" alt="ferry" />
      </div>

      <div id="house2l" class="draggable ui-widget-content" >
        <img src="images/house2l.png" alt="two level house" />
      </div>

      <div id="houseSvg" class="draggable ui-widget-content"> 
        <img src="images/house.svg" alt="house" type="image/svg+xml" /> SVG
      </div>

      <div id="housePng" class="draggable ui-widget-content">
        <img src="images/house.png" alt="house" />
      </div>

      <div id="houseSF" class="draggable ui-widget-content" >
        <img src="images/housesf.png" alt="SF house" />
      </div>

      <div id="street1" class="draggable ui-widget-content street" >
        <img src="images/street.png" alt="street">
      </div>

      <div id="street2" class="draggable ui-widget-content street" >
        <img src="images/street.png" alt="street">
      </div>

      <div id="street3" class="draggable ui-widget-content street" >
        <img src="images/street.png" alt="street">
      </div>

      <div id="street4" class="draggable ui-widget-content street" >
        <img src="images/street.png" alt="street">
      </div>

    </div> 
    <script>
    // code to make the active div move to the front
    // code from http://www.codingforums.com/javascript-programming/260289-bring-div-element-front-click.html

      // create an array to hold the (buildings, streets, landmarks) element's id
      var ids=[],
      // grab all the divs (each icon) and put it into thedivs
      thedivs = document.getElementById("canvas").getElementsByTagName("div");

      for (var i = 0; i < thedivs.length; i++) {

        // add the id of each div to the ids array
        //alert(thedivs[i].id);
        ids.push(thedivs[i].id);


        thedivs[i].onclick = function() {

          for (var a = 0; a < ids.length; a++) {
            if (this.id == ids[a]) {
              // take current id that matches the selected id and move it to the end
              ids.push(ids.splice(a,1));
            }
            document.getElementById(ids[a]).style.zIndex=a;     
          }
        }
      }
    </script>
  </div>
  <input type="button" value="save" onclick="saveAction()">

  <script>
        //Cycle through images and grab their x/y positions

        var saveAction = function(){

        elementNames = document.getElementById("canvas").getElementsByTagName("div");
        for(var i = 0; i < elementNames.length; i++)
        {
        var idName = $( "#" + elementNames[i].id);


         var offset = idName.offset();
         alert("Left pos: " + offset.left + " Top pos: " + offset.top);
        }


    };
  </script>
</div>
</body>
</html>

I have placed the Javascript in assets/javascripts/custom_map.js and I have placed the html / css in my new_map.html.erb view. The images are showing up fine in the Rails app but they are not draggable. How can I fix this? Thanks!

Whoppa
  • 949
  • 3
  • 13
  • 23

2 Answers2

1

Perhaps your load order is incorrect or your assets path is wrong. Try linking your script as the last thing on your page and wrap everything in it inside a jquery ready function:

    $(function() {
      // all your scripts here
    });

Also try viewing your source and making sure that your .js file is serving correctly It should be /assets/yourjs.js rather than /assets/javascripts/yourjs.js

Also, I think you may be able to use the jquery ui stack function to make items settle on top (not sure, you might want to try it):

$( ".draggable" ).draggable({ stack: ".draggable" });
Vinnie Pepi
  • 166
  • 4
0

Without knowing the specific errors you're receiving, I can only detail why you're having a problem, and how to resolve it generally:


Unobtrusive

You should never put javascript in your HTML code (known as inline JS). Problems being that it's messy & can be easily tampered with... hence making it relatively insecure, and generally seen as amateurish

A better way is to use unobtrusive JS (where the JS is stored in files loaded outside the scope of HTML). Rails uses the asset pipeline for this:

#app/assets/javascripts/application.js
var ready = function() { // -> you said JQuery :)
      $( ".draggable" ).draggable({ grid: [10,10] });
      $( "#draggable4" ).draggable({ grid: [ 20, 20 ], snap: true });

      /////////////////////////////////

      var ids=[],
      // grab all the divs (each icon) and put it into thedivs
      thedivs = document.getElementById("canvas").getElementsByTagName("div");

      for (var i = 0; i < thedivs.length; i++) {

        // add the id of each div to the ids array
        //alert(thedivs[i].id);
        ids.push(thedivs[i].id);


        thedivs[i].onclick = function() {

          for (var a = 0; a < ids.length; a++) {
            if (this.id == ids[a]) {
              // take current id that matches the selected id and move it to the end
              ids.push(ids.splice(a,1));
            }
            document.getElementById(ids[a]).style.zIndex=a;     
          }
        }
      }
 };
 $(document).on("page:load ready", ready);

If you migrate your JS from your views and put into your asset files, you'll be in a much better position to give us feedback, which we can then use to help fix your problem further

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147