Rendering a Gmap through an AJAX call with Gmaps4rails - ruby-on-rails

There are topics that try to cover this here: Gmaps4rails : map not showing when loaded dynamically and especially here: Rendering google map using gmaps4rails through Ajax, also watched the screencast in which a gmap is dynamically updated but I still don't seem to get it work.
I am trying to load the map in a drop-down tab only if a button is clicked displaying the direction between a user and an offer. In my _location.html.erb partial I have:
<%= gmaps({ "direction" => { "data" => { "from" => current_user.location, "to" => #offer.location } } })%>
(the locations are addresses)
Now this works nicely when the partial is rendered immediately. If I however try to render the partial over an AJAX call later after the whole page has already loaded initially, the gmap is not displayed. Is it possible to initialize and render the gmap through an AJAX call and display directions then?

The reason is quite simple: the partial contains much javascript you can't load and execute this way.
So you can't use RJS there.
The proper way to do is UJS: get data with an AJAX call and render the result. In the following code, I use jQuery.
In your view add:
//include google script
<script type="text/javascript" src='http://maps.google.com/maps/api/js?sensor=false&libraries=geometry'></script>
//include gmaps4rails javascript
<%=javascript_include_tag 'gmaps4rails' %>
<script type="text/javascript" charset="utf-8">
//load map when button click (replace with what you want)
$('#ajax_map').click(function(){
//you have to set a size to the div otherwise the map won't display, that's the purpose of these css classes
$('#map_container').addClass('map_container');
$('#gmaps4rails_map').addClass('gmaps4rails_map');
//create the map object
Gmaps4Rails.initialize();
//of course, replace these two with your dynamic data, you'd have to use some $.ajax jQuery method.
Gmaps4Rails.direction_conf.origin = 'toulon, france';
Gmaps4Rails.direction_conf.destination = 'paris, france';
//read the js file, you can customize much more: https://github.com/apneadiving/Google-Maps-for-Rails/blob/master/public/javascripts/gmaps4rails.js
Gmaps4Rails.create_direction();
});
</script>
<div id="map_container">
<div id="gmaps4rails_map"></div>
</div>
<button type="button" id="ajax_map">Ajax Map</button>
Add the following class in your CSS:
#map-container {
width: 800px;
}
#gmaps4rails_map {
width: 800px;
height: 400px;
}

Related

Can't get this simple Google Autocomplete script to work (Rails)

I have this at the bottom of a form partial, which worked previously when I loaded it through application.html.erb, but have since decided to replace it in application.html.erb with Google Maps.
_new.html.erb (with the field appropriately id'd). straight up doesn't work, can't figure out why.
<script>
$(document).ready(function(){
var autocomplete = new google.maps.places.Autocomplete(document.getElementById("autocomplete"));
});
function initAutocomplete(){
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCFm7OzAKuPbEa48b_aZ4S6JqMGVUCwwFs&libraries=places&callback=initAutocomplete"
async defer></script>
Try moving
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCFm7OzAKuPbEa48b_aZ4S6JqMGVUCwwFs&libraries=places&callback=initAutocomplete"
async defer></script>
to the in application.html.erb head tag
Then put
initAutocomplete = ->
$(document).ready ->
autocomplete = new (google.maps.places.Autocomplete)(document.getElementById('autocomplete'))
return
Into a coffeescript for you front page, or use your existing script inline of the partial to test if you need to.

Disable entire jqGrid

I have been looking for methods on how to disable a jqGrid and I found some:
Using BlockUI plugin: http://jquery.malsup.com/block/
Using jqGrid options: loadui and set it to 'block'
First option is a great solution (I have not tried yet) and it is clearer maybe but I want to avoid using plugins if I can whenever I can do it by setting object properties so I am trying the second option but it is not working for me, jqGrid continues enabled.
My jqgrid in my asp.net mvc 4 view:
<div id="jqGrid">
#Html.Partial("../Grids/_PartialGrid")
</div>
and _PartialGrid:
<table id="_compGrid" cellpadding="0" cellspacing="0">
</table>
<div id="_compPager" style="text-align: center;">
</div>
so in the view, in script section I perform below on document ready and depending on the status of a property in my model (I disable it if id>0, otherwise I enable it on page reload):
#section scripts
{
#Content.Script("/Grids/CompGrid.js", Url) // Content is a helper javascript loader (see end of this post)
}
<script type="text/javascript">
$(document).ready(function () {
showGrid();
var disableCompGrid = #Html.Raw(Json.Encode(Model.ItemCompViewModel));
setStatusCompGrid(disableCompGrid.id > 0);
}
</script>
CompGrid.js is:
function showGrid() {
$('#_compGrid').jqGrid({
caption: paramFromView.Caption,
colNames: ....
}
function setStatusCompGrid(disabled) {
$('#_compGrid').jqGrid({
loadui: 'block',
loadtext: 'Processing...'
});
}
In the code above, also I have tried to pass as parameter disabled to showGrid function and depending on if it is true or false to set a variable to 'block' or 'enable' respectively and then setting loadui property with this variable but it is not working.
Content.cshtml:
#using System.Web.Mvc;
#helper Script(string scriptName, UrlHelper url)
{
<script src="#url.Content(string.Format("~/Scripts/{0}", scriptName))" type="text/javascript"></script>
}
Any ideas?
It's important to understand that the call $('#_compGrid').jqGrid({...}); converts initial empty <table id="_compGrid"></table> element to relatively complex structure of dives and tables. So you can do such call only once. Such call creates and initialize the grid. In other words the function showGrid has bad name. The function can be called only once. The second call of it will test that the grid already exist and it will do nothing. If you need to change some parameters of existing grid you can use setGridParam method.
In the case you can use absolutely another solution to block the grid. After the call $('#_compGrid').jqGrid({...}); the DOM element of the initial table get some expandos - new property or method. For example $('#_compGrid')[0] will contains grid property which contains beginReq and endReq methods. So you can first create the grid (in the showGrid function) and include options loadui: 'block' and loadtext: 'Processing...' in the list of options which you use. Then if you need to block the grid later you can use
$('#_compGrid')[0].grid.beginReq();
and the code
$('#_compGrid')[0].grid.endReq();
to remove blocking. See the demo which demonstrates this. Alternatively you can show overlays created by jqGrid manually like I described in the answer. The code will be simple enough:
var gridId = "_compGrid"; // id of the grid
...
$("#lui_" + gridId).show();
$("#load_" + gridId).text("Processing...").show();
to show the overlay and
$("#lui_" + gridId).hide();
$("#load_" + gridId).hide();
to hide the overlay. See another demo which works exactly like the first one.
you don't need any plugin. Just add/remove css:
.disabled {
pointer-events: none;
//optional
opacity: 0.4;
}
DEMO

Is there any conflict between AngularJS and jQuery(UI)?

I try to make the items of a list draggable, but it doesn't work. jQuery doesn't seem to add the ui-draggable class, or maybe Angular removes it.
Javascript
$('.results_video').draggable({
});
HTML
<div class="results_video" ng-repeat="video in results.list">
{{video.title}}
</div>
Note that if I just write the following html, it works
<div class="results_video"></div>
Any suggestions?
I have found the solution. I need to make these divs draggable after they have been loaded. In my case:
var VideoCtrl = function ($scope){
$scope.$watch('search', function(){
//Some code that updates the divs
$('.results_video').draggable();
});
};

jQuery UI tabs: How do I load a specific element from a different page?

I have jQuery UI tabs set up, but a problem that I'm having with links to different pages is that they load all contents of the page into the tab. This includes the footer, header, and other navbars that I don't want in the tab. What if I would only like to load a single ID from that page?
My tabs are set up this way:
<div id="mytabs">
<ul>
<li>Awesome page</li>
<li>Foo</li>
</ul>
</div>
Nothing much going on in the jQuery...
$(function() {
$( "#mytabs" ).tabs();
});
Let's say this is the html of "awesomepage" (that the first link targets):
<html>
<head>
<title>awesome page</title>
</head>
<body>
<div id="header">bla</div>
<div id="awesomeness">awesomeness!</div>
<div id="footer">fdsfd</div>
</body>
</html>
...And I only want the tab to load #awesomeness from the page. How would I go about doing this? I've read into some guides that do that by adding a data-target="#youridhere" attribute to the HTML, but I'm still confused on how to implement the javascript. It seems like this is a convenient solution, as I won't be targeting the same ID in every page. Any clues on how to get the javascript working?
Thanks in advance!
The function that allow to load partial code of the response is the $.load() function.
Unfortunately, the tabs() feature does not use this function but use $.ajax instead.
You can try this solution:
You can try to stop the default processing on the beforeLoad callback and manage your ajax call with the $.load() method.
(base on the 1.9 documentation, you may should adapt)
$('#tabs').tabs({
// Callback run when selecting a tab
beforeLoad: function(event, ui) {
// If the panel is already populated do nothing
if (ui.panel.children().size() > 0)
return false;
// Make your own ajax load (with fragment feature)
ui.panel.load(ui.tab.attr('href') + ' #yourFragment');
// stop the default process (default ajax call should not be launched)
return false;
});
NOTICE: I'm not sure about extracting the URL with ui.tab.attr('href'), check before what object is ui.tab, but it should be easy to retrieve the href parameter.
Good luck
Got the solution :) Using one of the answers as a reference point, the tabs can now load a single element specified in the data-target attribute. Here is the modified version:
$(function() {
$('#tabs').tabs(
{
beforeLoad: function(event, ui) {
if (ui.panel.children().size() > 0)
return false;
ui.panel.load($('a', ui.tab).attr('href') + $('a', ui.tab).attr('data-target'));
return false;
}
});
});

Load page to a div jQuery Mobile

I want to load the content of a page that is in another folder (eg: "files/pages/example.html") for the div container by clicking on the button in jQuery Mobile!
How to do it?
<div data-role="page">
<div id="container" data-role="content"><button id="clickButton">Click me!</button></div>
</div>
The $.mobile.loadPage is the method you need. It allows you to load an external html file and insert it into the dom. Default for this method is to load it as an entire page, so you have to specify the options to load it into a dom element. This is an example (and untested) code:
$('#clickButton').on("click",function(){
$.mobile.loadPage("theURLofThePage",{pageContainer: $('#container')})
});
now, don't forget about the crossDomain security problem. I managed to make this work in firefox by adding:
$("#landingPage").live('pageinit', function() {
jQuery.support.cors = true;
$.mobile.allowCrossDomainPages=true;
});
Also, the page you are loading must be wrapped in a data-role=page div (let's say it has id='secondPage'). After the load, trigger on the data-role=page with id=secondPage div:
$('#secondPage").trigger('pagecreate');

Resources