I am unable to get a Javascript callback to work with gmaps4_rails when the map has loaded or is in the 'idle' state.
Based on the wiki and this other SO question Dynamically load Google Maps Markers with gmaps4rails I thought this would fire all of the alerts in this view:
<%= gmaps(:map_options => {:detect_location => true,
:center_on_user => true,
:auto_zoom => true,
:zoom => 12,
:auto_adjust => false},
:markers => {:data => #json,
:options => {:processsing => "#json",
:list_container => "markers_list",
:do_clustering => true
} }) %>
<ul id="markers_list"> </ul>
<script type="text/javascript" charset="utf-8">
alert("About to register callback");
Gmaps.map.callback = function() {
alert("Map Loaded Callback Reached");
}
function gmaps4rails_callback() {
alert("gmaps4_rails callback");
}
</script>
<%= yield :scripts %>
Instead I only get the "about to register callback" alert. The other functions never seem to be called. I have a feeling I'm misunderstanding something about the namespace but any insight would be appreciated- I'm trying to get things setup to refresh from a JSON endpoint as the map moved but I'm not having a lot of luck getting past this first step of making sure I can trigger a callback.
I should note the map appears normally and my initial data is all there.
As per documentation here, you must wrap the js code in a content_for :scripts
Why?
because gmaps4rails js code should be loaded first.
Related
Novice here, having some difficulties implementing an autocomplete using Searchkick and Typeahead/bloodhound.
First of all I have a index/welcome home page where I have my input field for my search box. This then searches over multiple models for names of different Cells and different cellular markers (not important for this).
First of all in my routes file, im unsure wether to have my autocomplete 'attached' to my "welcome" route or my "Cells" route, I've tried both but doesn't seem to make a difference, currently it is set as this:
resources :cells do
collection do
match 'autocomplete' => 'welcome#autocomplete', via: [:get], as: :autocomplete
end
end
resources :welcome #index / home page
my form input is:
<%= form_tag(#Search, :action => 'index', :method => "get", id: "search-form") do %>
<%= text_field_tag(:q, nil, placeholder: "Search...", class: "form-control rounded-left typeahead", autocomplete: "off") %>
<% end %>
My model is as follows:
searchkick text_start: [:name], callbacks: :async, suggest: [:name], word_start: [:name]
and my controller action:
def autocomplete
render json: Cell.search(params[:q], {
fields: ["name^5"],
autocomplete: true,
limit: 5,
load: false,
misspellings: false
}).map(&:name)
end
finally the javascript:
<script src="typeahead.bundle.js"></script>
<script>
var Cells = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/welcome/autocomplete?query=%QUERY',
wildcard: '%QUERY'
}
});
$('#typeahead').typeahead(null, {
source: Cells
});
</script>
I guess I am just very confused on how to properly set this up, I'm finding the Searchkick docs to be difficult to extrapolate to my purposes as I'm pretty novice at all this :) If anyone is able to help or point me to a good guide (that isn't years old) that would be amazing, as I'm pretty sure I'm just going around in circles. Is this the best way to go about implementing an autocomplete or is there a better way to do this?
Thanks for reading, and thanks for any help :)
A quick update for any future readers:
Im certain in the routes, the code for your autocomplete must point towards your controller that has your autocomplete method, for me it is my welcome controller.
resources :welcome do
collection do
match 'autocomplete' => 'welcome#autocomplete', via: [:get], as: :autocomplete
end
end
Im happy with my autocomplete method in my controller and am satisfied that I need the current javascript (currently in tags in my html
<script>
var autocomplete = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/welcome/autocomplete?q=%QUERY',
wildcard: '%QUERY'
}
});
$('#typeahead').typeahead(null, {
source: autocomplete
});
</script>
var autocomplete variable needs to be used below for the source: (I didn't realise this before)
still having difficulties as the autocomplete is still not working but I think I'm making progress
I'm using Bootstrap-sass and formtastic in my Rails application, and I'm not sure why the bootstrap-typeahead feature isn't working.
Form partial:
<%= f.input :tag, :input_html => { :'data-provide' => "typeahead", :'data-source' => '["hello", "hellow", "heaven", "helo", "herr"]' } %>
application.js manifest:
//= require bootstrap-typeahead //typeahead is correctly loaded, checked with firebug
result HTML source code:
<input :data-minLength="2" data-provide="typeahead" data-source="["hello", "hellow", "heaven", "helo", "herr"]"
In the end, I will need to customize typeahead to get the performance I want, but even this simple javascript isn't working for some reason. I cant find anything wrong with the code. Could anyone help me?
UPDATE:
I tried it in the javascript way as follows:
<script> //call typeahead
$(function() {
$('input#type_ahead').typeahead({
'source' : ["hello", "heaven", "heythere"]
});
})
</script>
<%= f.input :tag_list, :input_html => { :id => "type_ahead" }, %> //input tag
And still it seems like typeahead fails to work. i.e) typing in "he" does not get me a dropdown of those three items in the above array. Does anyone have an idea?
I think you need to set html_safe for:
{ :'data-source' => '["hello", "hellow", "heaven", "helo", "herr"]'.html_safe }
Have you called the typeahead() method when your page loads? You need to do something like this;
$(function() {
$('input').typeahead();
})
You'll need to assign a class or id to your input to bind the typeahead to it specifically (Rails probably has assigned an id to it automatically, I'm presuming you've omitted it specifically)
$(function() {
$('input#my-tag-field-with-a-cool-typeahead').typeahead();
})
edit:
The following worked for me. It'll take a bit of modification to the rails part to fit your situation, but this definitely works.
<script>
$(function() {
$('input#type_ahead').typeahead()
}
</script>
<%= text_field_tag :test_type, '', data: {provide: 'typeahead', source: "['hello','heythere','heaven']"} %>
I am adding google maps support with apneadiving / Google-Maps-for-Rails (thanks awesome gem)
I am finding one slight glitch, however, which very likely is my fault.
auto_zoom works great when there are multiple markers. However, when there is only one marker it is zoomed in to the max level which is not pretty.
"zoom" will only work when auto_zoom is false, so that's not what I want.
So therefore you could use "maxZoom" but now users cannot zoom in manually beyond that point which is not what I want.
Is there a way around this? Is my explanation making sense? Is this a limitation of Google Maps API?
Thanks...
This behavior is due to the auto_zoom built-in function in the google maps api.
One work around to this is to set it to false in the gmaps method:
<%= gmaps({
"map_options" => { "auto_zoom" => false},
"markers" => { "data" => #json }
})
%>
And then use the gmaps4rails_callback to fit your needs (be sure to have at least version 0.7.9)
<script type="text/javascript" charset="utf-8">
function gmaps4rails_callback() {
if (Gmaps4Rails.markers.length == 1) {
//only one marker, choose the zoom level you expect
Gmaps4Rails.map.setZoom(2);
}
else{
//more than one marker, let's auto_zoom
Gmaps4Rails.map_options.auto_zoom = true;
Gmaps4Rails.adjust_map_to_bounds();
}
}
</script>
I achieved this in a slightly different way as I know that I'll only ever have one marker on my map. I'm relatively new to rails, but this method feels a bit "cleaner" than using JS in your view.
I've got lat and lng stored in my model (encoded by geokit at time of creation), so did the following in my view:
<%= gmaps({
"map_options" => {"auto_zoom" => false, "zoom" => 15, "center_latitude" => #listing.lat, "center_longitude" => #listing.lng },
"markers" => {"data" => #markers }
})
%>
#markers is my JSON created by blah.to_gmaps4rails, and "listing" is my model.
thanks this helped me...
{"auto_zoom" => false, "zoom" => 15, "center_latitude" => #listing.lat, "center_longitude" => #listing.lng },
"markers" => {"data" => #markers }
})
%>
I currently have a rails webpage that uses the jRails and the jQuery library to run some ajax functions.
So far everything is working, including the delayedObserver plugin, which suggests that jRails is actually being put to use. However my 'drop_receiving_element' doesn't seem to work. This the Rails code:
<%= drop_receiving_element drop_id,
:onDrop => "function(drag_element, drop_element, event){
if (confirm(\"#{escape_javascript(_('This will remove User from this Group, are you sure?'))}\"))
{#{remote_function(:update => 'module_content',
:url => {:controller => :projects,
:action => :member_delete,
:id => #project.id},
:with => "'u=' + encodeURIComponent(drag_element.id)"
)};}
}",
:accept => 'RolesUsersSelection',
:hoverclass => "#{drop_class}_active"
%>
Which results in the following Javascript Code
<script type="text/javascript">
//<![CDATA[
jQuery('#RemoveThisMember').droppable({accept:'RolesUsersSelection', drop:function(drag_element, drop_element, event){
if (confirm("This will remove User from this Group, are you sure?"))
{jQuery.ajax({data:'u=' + encodeURIComponent(drag_element.id), success:function(request){jQuery('#module_content').html(request);}, type:'post', url:'/of/projects/11/member_delete'});}
}, hoverClass:'ProjectRoleDropDelete_active'})
//]]>
</script>
Yet I'm stumped as to why this isn't working.
This is the function called in the jRails.rb
def drop_receiving_element_js(element_id, options = {})
#convert similar options
options[:hoverClass] = options.delete(:hoverclass) if options[:hoverclass]
options[:drop] = options.delete(:onDrop) if options[:onDrop]
if options[:drop] || options[:url]
options[:with] ||= "'id=' + encodeURIComponent(#{JQUERY_VAR}(ui.draggable).attr('id'))"
options[:drop] ||= "function(ev, ui){" + remote_function(options) + "}"
end
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept]
[:activeClass, :hoverClass, :tolerance].each do |option|
options[option] = "'#{options[option]}'" if options[option]
end
%(#{JQUERY_VAR}('#{jquery_id(element_id)}').droppable(#{options_for_javascript(options)});)
end
Any ideas?
Thanks,
Turns out because I've switched over to jQuery, the parameters for
function(drag_element, drop_element, event)
were incorrect. Those are the correct parameters for prototype. They should read
function (ui,event)
if your using the jQuery library.
Is there a way to generate both a Javascript function call and an Ajax call in the same observe_form tag? For example, something like this:
<%= observe_form 'user_filter_form', :url => { :action => :process }, :function => :fix_fields %>
Thanks!!
Your best bet here is to dig into the actual JavaScript instead of relying on the helpers. The helpers can only get you so far. What you want is something along these lines:
<script type="text/javascript">
new Form.EventObserver('user_filter_form', function(element, value){
fix_fields();
new Ajax.Request("/YOUR_CONTROLLER/process");
}
</script>
However, if you really want to rely on the Rails helpers you can do something like:
<%= observe_form 'user_filter_form', :function => "fix_fields(); #{remote_function(:url => { :action => :process })}" %>
Use :before or :after options instead of :function, depending on whether you want your function called before of after the Ajax request.
See documentation of link_to_remote helper for common options that can be passed to all the Ajax helpers like observe_form