Problems with Gmaps.map.replaceMarkers: Gmaps.map is undefined - ruby-on-rails

I am trying to dynamically change the markers in Gmaps4Rails based on a user search form. I am using the code below.
The problem I am encountering is that the call to Gmaps.map.replaceMarkers within $('#locations_search').submit gives an error: Gmaps.map is undefined.
I checked using the javascript debbuger, and indeed once I enter the submit function (I have a breakpoint there), Gmaps.map is undefined. When stopping with a breakpoint in the first lines of Gmaps.map.callback, the object Gmaps.map is defined.
Probably I am missing something. It seems to be some variable scope problem here?
Gmaps.map.callback = function() {
var firstMarker = Gmaps.map.markers[0];
var map = Gmaps.map.map;
firstMarker.infowindow.open(map, firstMarker.serviceObject);
$('#locations_search').submit(function () {
var url = '/locations.json/?' + $(this).serialize();
$.getJSON(url, function(data){
Gmaps.map.replaceMarkers(data);
});
$.get(this.action, $(this).serialize(), null, 'script');
return false;
});
}
Thanks a lot!

It's just a question of script order.
Gmaps.map is created in your view when
You call either gmaps or gmaps4rails helpers.
Solution:
Add your scripts after your call to the gem's helpers
wrap your js code in <% content_for :scripts do %> code <% end %>
in your view:
<%= gmaps(...) %>
<% content_for :scripts do %>
<script type="text/javascript">
Gmaps.map.callback = function() { ... }
</script>
<% end %>
Gmaps.map.callback = function() {
var namespace = Gmaps.map;
var firstMarker = namespace.markers[0];
var map = namespace.map;
firstMarker.infowindow.open(map, firstMarker.serviceObject);
$('#locations_search').submit(function () {
var url = '/locations.json/?' + $(this).serialize();
$.getJSON(url, function(data){
namespace.replaceMarkers(data);
});
$.get(this.action, $(this).serialize(), null, 'script');
return false;
});
}

Related

Rails, gmaps4rails: Accessing javascript variable from within partial

Users can post 'notices' and these are displayed in users/show.html.erb in their 'notice feed'. Each notice has a :latitude and a :longitude and an associated marker on a google map.
I'm trying to make the marker change colour when the user hovers over the notice in the feed. I've given the marker the same id as the notice with marker.json({ id: notice.id }). In the notice partial, each notice is uniquely identified by its id: <li id="notice-<%= notice.id %>">. The problem is accessing 'markers' from within the notice partial. I want to use the code markers[<%= notice.id %>] but how do I pass 'markers' from the show javascript to the partial javascript?
Alternatively, I could do it all inside the show javascript, but the problems remains: how would I access the notice id from within the show javascript?
Users_controller.rb:
def show
#notice = #character.notices.build
#notice_feed_items = current_user.notice_feed.paginate(page: params[:notices_page])
#hash = Gmaps4rails.build_markers(#notice_feed_items) do |notice, marker|
marker.lat notice.latitude
marker.lng notice.longitude
marker.infowindow notice.content
marker.json({ id: notice.id })
end
redirect_to root_url and return unless #user.activated
end
users/show/html.erb:
<% if #notice_feed_items.any? %>
<ol class="posts">
<%= render #notice_feed_items %>
</ol>
<%= will_paginate #notice_feed_items, param_name: 'notices_page' %>
<% end %>
<script type="text/javascript">
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
markers = handler.addMarkers(<%=raw #hash.to_json %>);
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
map = handler.getMap();
var update_timeout = null;
google.maps.event.addListener(map, 'click', function(event){
update_timeout = setTimeout(function(){
placeMarker(event.latLng);
fillInForm(event.latLng);
document.getElementById("dropfield").focus();
}, 300);
});
google.maps.event.addListener(map, 'dblclick', function(event) {
clearTimeout(update_timeout);
});
});
function placeMarker(latLng) {
var marker = new google.maps.Marker({
position: latLng,
map: map,
draggable: false
});
}
function fillInForm(latLng) {
$('#notice_latitude').val(latLng.lat());
$('#notice_longitude').val(latLng.lng());
}
</script>
_notice.html.erb:
<li id="notice-<%= notice.id %>">
.
.
.
</li>
<script type="text/javascript">
document.getElementById("notice-<%= notice.id %>").onmouseover=function(){
markers[<%= notice.id %>].setIcon("markers/blue_MarkerA.png");
}
document.getElementById("notice-<%= notice.id %>").onmouseout=function(){
markers[<%= notice.id %>].setIcon("markers/yellow_MarkerA.png");
}
</script>
EDIT:
I'm trying to solve the problem by doing it all in show.html.erb with the following code, using grep:
<script type="text/javascript">
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
markers = handler.addMarkers(<%=raw #hash.to_json %>);
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
map = handler.getMap();
var update_timeout = null;
google.maps.event.addListener(map, 'click', function(event){
update_timeout = setTimeout(function(){
placeMarker(event.latLng);
fillInForm(event.latLng);
document.getElementById("dropfield").focus();
}, 300);
});
google.maps.event.addListener(map, 'dblclick', function(event) {
clearTimeout(update_timeout);
});
});
function placeMarker(latLng) {
var marker = new google.maps.Marker({
position: latLng,
map: map,
draggable: false
});
}
function fillInForm(latLng) {
$('#notice_latitude').val(latLng.lat());
$('#notice_longitude').val(latLng.lng());
}
$("#notice_list li").on('mouseenter', function(){
var id = $(this).attr('id');
$.grep(markers, function(m){return m.id == id;})[0].setIcon("markers/blue_MarkerA.png");
}).on('mouseleave', function(){
var id=$(this).attr('id');
$.grep(markers, function(m){return m.id == id;})[0].setIcon("markers/yellow_MarkerA.png");
});
</script>
... but it isn't working. I think the problem is that trying to access the id of each marker in markers with m.id isn't working. I tried to get it to print out markers[0].id but nothing happened, it seems you can't access the marker id with markers[0].id?! (I checked markers.length wasn't zero. It wasn't - the map is full of markers).
So, how do you access the id of an element of markers if markers[0].id doesn't work??
marker haven't id attribute. To have a reference of each marker you could use the index of the markers array (adding markers one per one).
# pseudocode
<% #notice_feed_items.each do |item| %>
markers[<%= item.id %>] = handler.addMarker(<%=raw item.to_json %>);
<% end %>

Getting Epiceditor to work in Ruby on Rails

I am trying to use epiceditor in a basic Ruby on Rails application. I followed the instructions on the webpage http://epiceditor.com/#. The epic editor window is not displaying for some reason...thanks
This is how I set up the code on my edit.html.erb view:
```
<head>
<meta charset="utf-8">
<script src="js/epiceditor.js"></script>
</head>
<body>
<div id="epiceditor"></div>
</body>
<script type="text/javascript">
var editor = new EpicEditor().load();
</script>
<h1>Edit Wiki</h1>
<%= form_for #mywiki do |f| %>
<div>
<%= f.label :title %>
<%= f.text_field :title, :size => 75 %>
</div>
<div>
<%= f.label :body %>
<%= f.text_area :body, :rows => "35", :cols => "75" %>
</div>
<%= f.submit %>
<% end %>
```
is there some valid CSS added?
After adding the css from epic editor's site, I got it working.
Ruby - 2.3.0
Rails - 4.2.5
Bootstrap 3 gem 'bootstrap-sass', '~> 3.3.6'
EpicEditor gem 'epic-editor-rails'
Ran bundle from my app root:
rails_app_root$ bundle
Updated /app/assets/stylesheets/application.scss
#import 'base/epiceditor';
//#import 'preview/bartik';
//#import 'preview/github';
//#import 'preview/preview-dark';
//#import 'editor/epic-dark';
//#import 'editor/epic-light';
// This is shown here for reference just to instruct that I have imported EpicEditor themes first.
#import "bootstrap-sprockets";
#import "bootstrap";
Note I have just imported base/epiceditor and others are commented out. The reason being they were overriding the Bootstrap styling which wasn't needed.
On my form partial /app/views/.../_form.html.haml under <form> element following things I added:
#myTextAreaContainer(style='display: none')
= text_area_tag("body", myText, id: 'myTextArea')
.form-group
= label_tag(nil, "My Text", class: "col-md-3 control-label")
#myTextEpicEditor.col-md-7
On my show view /app/views/..../show.html.haml
.row
.col-md-10
#myDetailsView.form-horizontal
%div(style='display: none')
= text_area_tag("myText", #my_text, id: 'viewMyTextTextArea')
.form-group
= label_tag(nil, "My Text", class: "col-sm-3 control-label")
#viewMyTextBodyEpicEditor.col-sm-6
In /app/assets/javascripts/custom.js
(function ($) {
isEmptyValue = function(value) {
return ( undefined === value || null === value || "" === value || ("" === value.replace(/[\n\r]/g, '')) )
}
myForm = function() {
return $("form#myForm");
};
// Note: EpicEditor requires just the id value not a jquery selector
// like "#myTextEpicEditor"
myFormEpicEditorContainerId = function() {
return "myTextEpicEditor";
}
// Note: EpicEditor requires just the id value not a jquery selector
// like "#myTextArea"
myFormTextAreaId = function() {
return "myTextArea";
}
myFormMyTextLocalStorageName = function() {
return "myTextEpicEditorLocalStorage";
}
myFormMyTextBodyFileName = function() {
return "myTextFile";
}
myFormEpicEditorOpts = function() {
var myTextEpicEditorOpts = {
container: myFormEpicEditorContainerId(),
textarea: myFormTextAreaId(),
localStorageName: myFormMyTextLocalStorageName(),
file: {
name: myFormMyTextBodyFileName(),
defaultContent: '',
autoSave: 100
},
};
return myTextEpicEditorOpts;
}
loadEpicEditorOnMyForm = function() {
var selector = "#" + myFormEpicEditorContainerId();
if ($(selector).length == 0) {
return;
}
var myFormEpicEditorInstance = new EpicEditor(myFormEpicEditorOpts()).load();
};
bindClickEventOnSaveBtnOnMyForm = function() {
var saveBtnObj = $("#saveBtn");
if (saveBtnObj.length == 0) {
return;
}
saveBtnObj.off("click").on("click", function(event) {
var myFormObj = myForm();
var myFormEpicEditorInstance = new EpicEditor(myFormEpicEditorOpts());
// console.log(myFormEpicEditorInstance);
var myText = myFormEpicEditorInstance.exportFile(myFormMyTextBodyFileName(), 'text');
// console.log(myText);
if (isEmptyValue(myText)) {
alert("Please enter text");
event.stopPropagation();
return false;
}
myFormObj.submit();
});
};
// Used for rendering EpicEditor in ONLY preview mode with only
// full screen button and when the epic editor is switched to
// full screen mode it hides the editor pane.
displaySavedMyTextPreview = function() {
var myDetailsView = $("#myDetailsView")
if (myDetailsView.length == 0) {
return;
};
var viewMyTextEpicEditorOpts = {
container: 'viewMyTextBodyEpicEditor',
textarea: 'viewMyTextTextArea',
button: {
preview: false,
edit: false,
fullscreen: true,
bar: "auto"
},
};
var viewMyTextEpicEditorInstance = new EpicEditor(viewMyTextEpicEditorOpts);
viewMyTextEpicEditorInstance.load(function() {
console.log("loaded");
viewMyTextEpicEditorInstance.preview();
});
viewMyTextEpicEditorInstance.on('fullscreenenter', function() {
// console.log("full screen enter");
$(viewMyTextEpicEditorInstance.getElement('editorIframe')).hide();
});
};
}) (jQuery);
var ready;
ready = function() {
loadEpicEditorOnMyForm();
bindClickEventOnSaveBtnOnMyForm();
displaySavedMyTextPreview();
};
$(document).ready(ready);
$(document).on('page:load', ready);
Note
The code shown above is working code. In case it doesn't work for you try looking for any mistakes made in typing the element selectors etc.
I assume that jQuery is available in the application.
Though I have not tried it but you can include multiple EpicEditors on the same page by passing in custom options like I have demonstrated.

Gmaps4rails: map does not show through ajax with erb data feeding but does when hard coded

I would like to use the gmaps4rails gem to display a map of items in a fancybox.
I followed carefully the remarks on the wiki concerning ajax call, i.e. scripts have to be included manually in the application layout, maps have to be loaded in a javascript (see gem wiki).
But I still not succeed completely to make the map displayed in the box.
On the other hand as I hard code coordinates in the javascript it works fine, the map is displayed in the fancybox and the markers appear.
Let me recap.
In my index view, I have a ajax call to the items index action:
<%= link_to "Show Map", items_path(:format => :js, :show_map => true), :remote => true, :class => 'fancybox' %>
In the controller, I populate the map data:
def index
#items=Item.all
if params[:show_map]
#map= #items.to_gmaps4rails
end
end
in the index.js.erb file, I put
<% if params[:show_map] %>
var content = "<%= escape_javascript( gmaps({:last_map => false})) %>";
$.fancybox({
'content': content,
'padding' : 20
});
Gmaps.map = new Gmaps4RailsGoogle();
Gmaps.load_map = function() {
Gmaps.map.initialize();
Gmaps.map.markers = <%= #map %>;
Gmaps.map.create_markers();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
Gmaps.loadMaps();
<% else %>
// blablabla
<% end %>
Where the markers are provided in the map object.
This does not work and instead of my map I got in the fancybox the code itself appearing.
Something like:
var content = "\n
\n
<\/div>\n<\/div>\n"; $.fancybox({ 'content': content, 'padding' : 20 }); Gmaps.map = new Gmaps4RailsGoogle(); Gmaps.load_map = function() {Gmaps.map.initialize();
//Gmaps.map.markers = [{"lat":50.294,"lng":5.857},{"lat":50.294,"lng":5.857},{"lat":50.548,"lng":4.918},{"lat":50.384,"lng":3.649},{"lat":50.384,"lng":3.649},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.054,"lng":5.195}];
Gmaps.map.markers = [{"lat":50.8483059,"lng":4.351783999999999},{"lat":50.496,"lng":5.066},{"lat":50.11,"lng":5.003},{"lat":50.11,"lng":5.003},{"lat":50.162,"lng":5.871},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.08,"lng":4.5760000000000005}];
Gmaps.map.create_markers(); Gmaps.map.adjustMapToBounds(); Gmaps.map.callback(); }; Gmaps.loadMaps();
When instead of the erb <%= #map %>, I hard code the markers, for instance:
Gmaps.map.markers = [{"lat":50.294,"lng":5.857},"lat":50.294,"lng":5.857},{"lat":50.548,"lng":4.918}];
It works!
Seems like I'm missing something in the json data type conversion. But I'm not expert to find what is going wrong.
Thanks for your help!
Just successfully tried:
Open
<div id="test" style="display:none;width:300px;">
<%= gmaps markers: { data: #json } , last_map: false %>
</div>
<script type="text/javascript">
$(".fancybox").fancybox({
openEffect : 'none',
closeEffect : 'none',
afterLoad : function() { Gmaps.loadMaps(); }
});
</script>
Ok, I've got what was not going well. Thanks to the following answer https://stackoverflow.com/a/12219016/1100674.
As I use the following syntax:
Gmaps.map.markers = <%= #map %>;
I get the json rendered as this:
Gmaps.map.markers = [{"lat":50.8483059,"lng":4.351783999999999},{"lat":50.11,"lng":5.003},{"lat":50.11,"lng":5.003},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.413,"lng":4.371}];
Whereas I use the raw() method,
Gmaps.map.markers = <%= raw(#map) %>;
I get the correct format.
Gmaps.map.markers = [{"lat":50.8483059,"lng":4.351783999999999},{"lat":50.11,"lng":5.003},{"lat":50.11,"lng":5.003},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.08,"lng":4.5760000000000005},{"lat":50.413,"lng":4.371}];

Passing Ajax Parameters to Rails Controller

I am trying to pass some parameters from my view via an AJAX call to a custom method fetch_info in my photos controller. My controller does not seem to be receiving the parameters. When I click on an image to initiate the AJAX call, I see the following in my terminal:
Processing by PhotosController#fetch_info as JSON
Parameters: {"id"=>"", "secret"=>""}
Completed 500 Internal Server Error in 267ms
FlickRaw::FailedResponse ('flickr.photos.getInfo' - Photo not found):
app/controllers/photos_controller.rb:38:in `fetch_info'
It looks like the fetch_info method is being called, but the parameters are empty. How should I be passing in my parameters through AJAX?
Here is my view. I also have my javascript in the view for the purpose of just getting this to work.
index.html.erb
<div class="body_container">
<div id="photos_container">
<% #photos_array.each do |p| %>
<%= link_to '#' do %>
<div class='each_photo_container', id='<%="#{p[:id]}"%>' >
<%= image_tag p[:s_url] %>
</div>
<% end %>
<!-- Load Modal onClick -->
<script type="text/javascript">
jQuery(function() {
$('#<%=p[:id]%>').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '<%=p[:id]%>';
var fetch_secret = '<%=p[:secret]%>';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id.val(), 'secret' : fetch_secret.val() }
});
return false;
});
});
</script>
<% end %>
<div class="basic_modal">
</div>
</div>
</div>
Here is my photos_controller.rb:
def fetch_info
puts params[:id]
puts params[:secret]
info = flickr.photos.getInfo(:photo_id => params[:id], :secret=> params[:secret])
end
You can use this code:
$('##{p[:id]}').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '#{p[:id]}';
var fetch_secret = '#{p[:secret]}';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id, 'secret' : fetch_secret }
});
return false;
})

How to add link to marker using gmaps4rails gem

I would like to add a marker with link in marker, so, when i click that marker, i will redirect to another page
Is anybody know to do it?
Thanks
I already added my code like this :
In controller:
#json = #businesses.results.to_gmaps4rails do |object|
"\"link\": \"#{root_url}\""
end
In view :
<%= gmaps4rails(#json) %>
<% content_for :scripts do %>
<script type="text/javascript">
function redirect_to(url) {
window.location = url;
};
Gmaps4Rails.callback = function() {
function say_yo(arg) { return function(){alert('yo '+ arg + '!' );};};
for (var i = 0; i < Gmaps4Rails.markers.length; ++i) {
google.maps.event.addListener(Gmaps4Rails.markers[i].google_object, 'click', redirect_to(Gmaps4Rails.markers[i].link));
}
}
</script>
<% end %>
Is it any wrong? because there just an info window that show after i clicked the marker(Not redirect to any page)
First include the link inside the json:
Model.all.to_gmaps4rails do |object|
"\"link\": \"your link as string\""
end
Then add the extra listeners in your view (beware to include this AFTER your call to the gmaps method):
<%= gmaps(whatever you need here) %>
<% content_for :scripts do %>
<script type="text/javascript">
function redirect_to(url) {
window.location = url;
};
Gmaps4Rails.callback = function() {
function say_yo(arg) { return function(){alert('yo '+ arg + '!' );};};
for (var i = 0; i < Gmaps4Rails.markers.length; ++i) {
google.maps.event.addListener(Gmaps4Rails.markers[i].google_object, 'click', redirect_to(Gmaps4Rails.markers[i].link));
}
}
</script>
<% end %>

Resources