I'm trying to put this autocomplete.js widget into my rails project: http://andymatthews.net/code/autocomplete/
It works fine when I use it as a standalone project without using rails- putting array.html, code.js and jqm.autoComplete-1.5.2.js in the same folder, and running array.html in my browser. I get the drop down, autocomplete menu in the widget. All works well.
But when I put it in a new rails project - a project made for the purpose of trying to get this widget to work, so there's definitely no code conflicts, it's styled correctly, but my drop down menu does not appear. Any ideas what I'm doing wrong?
In my application.html.erb file I have code from the header of array.html, plus the standard rails header material - stylesheet_link_tag, javascript_include_tag and csrf:
<head>
<title>AutocompleteTest</title>
<meta content="initial-scale=1, maximum-scale=1, user-scalable=0" name="viewport" />
<meta name="viewport" content="width=device-width" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
In my assets/javascripts folder I've pasted code.js and jqm.autoComplete-1.5.2.js and in my application.js file I have:
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require code
//= require jqm.autoComplete-1.5.2
My view code for the autocomplete js is:
<div data-role="content" class="ui-content" role="main">
<p>
In this example autoComplete uses a local array comprised of strings. This also shows an example of the matchFromStart property set to false.
</p>
<p>
<input type="text" id="searchField" placeholder="Categories" class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset ui-focus">
</p><ul id="suggestions" data-role="listview" data-inset="true" class="ui-listview ui-listview-inset ui-corner-all ui-shadow"></ul>
<p></p>
</div>
In application.html.erb I yield to auto_complete.html.erb, which contains:
<div data-role="content">
<p>
In this example autoComplete uses a local array comprised of strings. This also shows an example of the matchFromStart property set to false.
</p>
<p>
<input type="text" id="searchField" placeholder="Categories">
<ul id="suggestions" data-role="listview" data-inset="true"></ul>
</p>
</div>
</div>
<script>
$("#mainPage").bind("pageshow", function(e) {
var data = ['C', 'Clojure', 'Jenny!', 'Java', 'Scala', 'Objective-C', 'C++', 'PHP', 'C#', '(Visual) Basic', 'Python', 'Perl', 'JavaScript', 'Ruby', 'Visual Basic .NET', 'Transact-SQL', 'Lisp', 'Pascal', 'Bash', 'PL/SQL', 'Delphi/Object Pascal', 'Ada', 'MATLAB'];
$("#searchField").autocomplete({
target: $('#suggestions'),
source: data,
link: 'target.html?term=',
minLength: 1,
matchFromStart: false
});
});
</script>
Any idea why it's not working or any ideas?
Related
I'm trying to see if I can get the Bootstrap datePicker (datePicker)to work in Grails v3.3.9/fields plugin 2.2.10
I've done a standalone page, that is I create a controller, and give it an action called 'ldt'.
I create grails view called ldt.gsp like this. When I hit trigger my controller in the browser - this simple page renders fine and datePicker works
<!DOCTYPE html>
<html>
<head>
<title>Bootstrap datepicket demo</title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script type='text/javascript' src='//code.jquery.com/jquery-1.8.3.js'></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker3.min.css">
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js"></script>
<script type='text/javascript'>
$(function(){
//$('.input-group.date').datepicker({
$('#datepicker').datepicker({
calendarWeeks: true,
todayHighlight: true,
autoclose: true
});
});
</script>
</head>
<body>
<div class="container">
<h1>Bootstrap datepicker</h1>
<div class="input-group date" id="datepicker">
<input type="text" class="form-control">
<span class="input-group-addon">
<i class="glyphicon glyphicon-calendar"></i>
</span>
</div>
</div>
</body>
</html>
You can see that here. This is not using normal Grails site mesh etc
So I tried to put the same into views/layouts/main.gsp
So here is the head section of my revised main.gsp. (I've not included Bootstrap nor jQuery as them come with grails application.js).
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>
<g:layoutTitle default="Grails"/>
</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<asset:link rel="icon" href="favicon.ico" type="image/x-ico"/>
<asset:stylesheet src="application.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker3.min.css">
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js"></script>
<script type='text/javascript'>
$(function(){
$('#datepicker').datepicker({
calendarWeeks: true,
todayHighlight: true,
autoclose: true
});
});
</script>
<g:layoutHead/>
<%-- header assets --%>
</head>....
Now I am trying to render a specific field in the domain class - which is of type LocalDateTime. To try and do this I have created a _fields/localDateTime/_wrapper.gsp that looks like this in which I setup the input control (as I did for the standalone page), but I give the input a start date time for now.
localDateTime/_wrapper.gsp
<%# page import="java.time.LocalDateTime; java.time.format.DateTimeFormatter" %>
<g:set var="localDateTimePattern" value="${message(code: 'default.localDateTime.format',default: 'yyyy-MM-dd HH:mm')}"/>
<div class="fieldcontain" >
<div class="container">
<div class="row">
<div class='col-sm-6'>
<div class="form-group">
<div class="input-group date" id='datetimepicker1' >
<label for=${this.pageScope.property}> ${this.pageScope.getVariable("label")} </label>
<input type='text' class="form-control" value="${java.time.LocalDateTime.now().toString()}"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
When I go this page in the browser it gets rendered, but the clickable field behaviour etc does not fire and the field has no calendar icon on the right hand side (this may be because Grails is loading Bootstrap 4, and when I tried the standalone with v4.3.1 the icon didn't render - but the click event still worked).
See rendered form here - using the 'edit' action which in turn is using standard scaffolds with <f:all which calls my _wrapper.gsp.
The string value of the date gets rendered fine (not formatted), but I get no click action and calendar doesn't pop up - no action at all. I've included a snip of the browser page inspection in the browser opened for the contractSignedDate property.
So if a standalone page gsp works just fine (albeit with Bootstrap 4 as loaded by Grails bau) does my click action not fire
So why can't the gsp action action fire when using the main.gsp/normal fields plugin/and _wrapper.gsp for java LocalDateTime? It worked for standalone gsp example so I know the datePicker works
How can I get the Bootstrap datepicker as described here working in a Grails scaffolded form?
PS it's not missing jqueryUI library - I've included 1.12.1 in both standalone and main.gsp see this image from inspector. Works fine on standalone but not using main.gsp and scaffolded forms
PS if I click into the scaffolded form property as shown in the _widget.gsp, the outer text box is highlighted in blue (which the bau grails rendered elements don't - so some form of click action is happening - just not getting a calendar to pop up.
This is very odd. When referenced on standalone gsp and link JS/CSS from CDN, the page worked.
If I add <meta name="layout" content="main" /> and had the page rendered via site mesh in main.gsp it would fail.
I tried many different combinations in the standalone page <head>, and basically the date picker doesn't seem to need the bootstrap js to work - but it does need the jQuery and it must be in the head section.
If you want the styles you need to include the bootstrap.css and the bootstrap-datepicker3 CSS.
<head>
<%--<meta name="layout" content="main" />--%>
<title>Bootstrap datepicket demo</title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<%--<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script> --%>
<script type='text/javascript' src='//code.jquery.com/jquery-3.3.1.js'></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker3.min.css">
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js"></script>
</head>
However if you uncommented the meta tag it would all stop. In the end to get this to work I had to edit the /assets/application.js and remove the entries for Bootstrap and jQuery using the local copies in /assets/javascripts, and instead reference these directly from the cdn in main.gsp.
So my working application.js looks like this - where I include my own LCM-app JS:
// This is a manifest file that'll be compiled into application.js.
//
// Any JavaScript file within this directory can be referenced here using a relative path.
//
// You're free to add application-wide JavaScript to this file, but it's generally better
// to create separate JavaScript files as needed.
//= require LCM-app
//= require popper.min
//= require_self
My LCM-app js just looks like this where my selector is using class selector - note you seem to have add the dot between group and date '.input-group.date' - but that becomes a space in your markup
// used by bootstrap date picker - matching class selector is for class class='.input-group date'
$(function(){
$('.input-group.date').datepicker({
calendarWeeks: true,
todayHighlight: true,
autoclose: true
});
});
I then went to main.gsp and edited in the cdn references that I had in the standlone page (asset plugin is now disabled for jQuery and Bootstrap)
main.gsp (head section) - you dont need jqueryUI for this to work
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>
<g:layoutTitle default="Grails"/>
</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<asset:link rel="icon" href="favicon.ico" type="image/x-ico"/>
<asset:stylesheet src="application.css"/>
<%-- <script type='text/javascript' src='//code.jquery.com/jquery-1.12.1.js'></script>--%>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script type='text/javascript' src='//code.jquery.com/jquery-3.3.1.js'></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker3.min.css">
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js"></script>
<g:layoutHead/>
<%-- header assets --%>
</head>
Now when you uncomment out the <meta> tag in the standalone page and remove the direct refs - then the main.gsp site mesh adds these back exactly as they were in the standalone page
Point your browser at the test page and it all works as normal.
It even works when I put the basic code into a taglib (you have to stop the escaping using the static encodeAsForTags and set to 'none' for your tag).
JdtDateTimeTagLib
class JavaDateTimeTagLib {
static defaultEncodeAs = [taglib:'html']
//static encodeAsForTags = [tagName: [taglib:'html'], otherTagName: [taglib:'none']]
static encodeAsForTags = [ jdtScaffoldField:'none']
static namespace = "jdt" //java8 date time name space for tags
GrailsNameUtils grailsNameUtils = new GrailsNameUtils()
def jdtScaffoldField = {attrs, body ->
assert grailsNameUtils
String propertyName = attrs.propertyName ?: "unknown"
String property = attrs.property ?: "unknown"
String value = attrs.value
String naturalName = grailsNameUtils.getNaturalName(propertyName)
String label = attrs.label ?: 'unknown'
String ldtStr = attrs.ldt
String page = """
<g:set var="localDateTimePattern" value="${message(code: 'default.localDateTime.format',default: 'yyyy-MM-dd HH:mm')}"/>
<div class="fieldcontain" >
<div class="container">
<div class="row">
<div class='col-sm-6'>
<div class="form-group form-inline">
<label class='control-label' for="$propertyName"> ${label} </label>
<div class="input-group date" >
<input type='text' class="form-control" value="${ldtStr?.toString()}"/>
<span class="input-group-addon">
<i class="glyphicon glyphicon-calendar"></i>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
"""
out << page
}
}
I can then simplify the _fields/localDateTime/_wrapper.gsp to use that tag like so
<%# page import="java.time.LocalDateTime; java.time.format.DateTimeFormatter" %>
<g:set var="localDateTimePattern" value="${message(code: 'default.localDateTime.format',default: 'yyyy-MM-dd HH:mm')}"/>
<jdt:jdtScaffoldField propertyName="xyc" label="my label"></jdt:jdtScaffoldField>
Now when you go to a normal grails edit action my field is rendered and the calendar actions.
I've lost variables in this version as I'm not getting the values passed to the wrapper and putting them forward into my tag - but I think that's not too hard. See working screen shot 'as-is'
Sadly the lest of the Grails scaffolding is using its own rendering so the CSS styles don't match, alignment is a bit out etc - but its an improvement if I can just get the submit action etc to take the selected date and convert pack to LocalDateTime to persist in the database.
Basically it would be better if the grails <g:datePicker could be 'fixed' to work with new Java time formats and use the Bootstrap picker - because the fields plugin invokes the <g:datePicker for ordinary Java Date but completely doesn't handle the Java 8 temporal stuff.
I have tried to 'find' where the grails <g: taglib is implemented (thought it was going to be in the GSP plugin or core projects - but I can't find it in either.
However whilst it's not ideal - its good enough for the mini demo using scaffolds I was going to show people - just looks a little clunky as it's not consistent.
I have the script block in GSP page as shown in the code below. But the script block is not responding. Instead of printing hello in the console of the page, I get the error undefined operator $. What can be the reason?
getSpecificQuestion.gsp
<html>
<head>
<script>
$('.index').click(function() {
console.log("hello")
});
</script>
<title> Test </title>
</head>
<body>
<div id="question">
<%= "question = $question"%>
</div>
<div id="indexButtons">
<g:each in="${(1..<11)}" var="i">
<input type="button" class="index" value="${i}"/>
</g:each>
</div>
</body>
</html>
Apparently your gsp did not include any jquery in it so it complained about the missing $
Make sure that you include jquery in your gsp before the your script block. If you are using the resources plugin you can do something like this:
<html>
<head>
<r:require module="jQuery1111"/>
<r:script>
$(function() {
$('.index').click(function() {
console.log("hello")
});
})
</r:script>
<title> Test </title>
</head>
<body>
<div id="question">
<%= "question = $question"%>
</div>
<div id="indexButtons">
<g:each in="${(1..<11)}" var="i">
<input type="button" class="index" value="${i}"/>
</g:each>
</div>
</body>
</html>
Using the tag will render your javascript at the bottom of the page after all the DOM elements have been rendered and ready to be manipulated by the scripts.
I'm running a rails 4 app and have installed v1.6 of the jquery geocomplete plugin to provide a google places autocomplete function.
I followed the instructions on the geocomplete github page (http://ubilabs.github.io/geocomplete/)
The plugin works perfectly when running on my localhost, but when I upload my app to heroku, the autocomplete simple doesn't work - the google map does not show and typing in the autocomplete text field doesn't trigger any response. In addition, no other javascript works on the page.
These are the scripts I'm running in my view file:
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$(function(){
$("#geocomplete").geocomplete({
map: ".map_canvas",
details: "form",
types: ["geocode", "establishment"],
});
$("#find").click(function(){
$("#geocomplete").trigger("geocode");
});
});
</script>
These are the files I'm requiring in my application.js file
//= require jquery
//= require jquery_ujs
//= require bootstrap.min
//= require turbolinks
//= require jquery.turbolinks
//= require jquery.geocomplete
//= require jquery.geocomplete.min
//= require underscore
//= require gmaps/google
//= require_tree .
This is the html from the top of the page in heroku:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link data-turbolinks-track="true" href="/assets/application-2b5264bcc7a1f63268dbbba57c51fade.css" media="all" rel="stylesheet" />
<script data-turbolinks-track="true" src="/assets/application-1a5a53ee82e1bcf8741700c933ffab84.js"></script>
<meta content="authenticity_token" name="csrf-param" />
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="/javascripts/html5shiv.js"></script>
<script src="/javascripts/respond.min.js"></script>
<![endif]-->
</head>
<body data-no-turbolink="true">
And html from lower down in the document where the google map/autocomplete resides:
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<style type="text/css" media="screen">
.map_canvas {
width: 600px;
height: 400px;
margin: 10px 20px 10px 0;
}
form { width: 1000px; float: left; }
</style>
<br />
<input id="geocomplete" type="text" placeholder="Type business name/address" size="70" />
<input id="find" type="button" value="Find" />
<div class="map_canvas"></div>
<div class="details">
<div><%= f.label :name %><br />
<%= f.text_field :name, { :geo => "name", class: "form-control"} %></div>
** other fields not shown here **
</div>
Really stuck in this one. Has any one had a similar problem?
Finally figured out what was wrong with this one.
There was nothing wrong with the code. I need to precompile assets before uploading to Heroku.
i.e. at the command line:
$ bundle exec rake assets:precompile RAILS_ENV=production
This solved the issue.
I'd recommend doing this whenever you've having javascript issues in Heroku.
I have attached screenshots at the bottom. I have tried the following the tips from IE8 issue with Twitter Bootstrap 3 to no avail. I have tried adding respond.js, adding the <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> meta tag, and ensuring my markup is correct. I have also ensured that both the html5shiv and respond.js are being loaded. Any idea what I'm doing wrong?
Relevant code
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<%= stylesheet_link_tag "application", :media => "all" %>
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.1/html5shiv.js" type="text/javascript"></script>
<script src="../../vendor/assets/js/respond.js"></script>
<![endif]-->
</head>
<body>
<header class="navbar navbar-inverse navbar-static-top" role='navigation'>
<div class='navbar-header'>
<a class="navbar-brand" href="/">Byrex</a>
</div>
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<ul class="dropdown-menu">
<li></li>
<li></li>
</ul>
</li>
</ul>
</header>
</body>
Expected/All Other Browsers
IE 8
You might try to use other sources of your scripts (and shiv 3.7):
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
IE 8 just blows, but that being said, it might help if you include calls for if the browser is IE8 --
<!--[if IE 8]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.1/html5shiv.js" type="text/javascript"></script>
<script src="../../vendor/assets/js/respond.js"></script>
I removed the "lt" because in recent experience, I had to do so to get IE8 to recognize it. You can also throw in custom overrides between those tags to fix any other IE8 stupidity.
I use SASS as views engine with built-in prettyfying option in config/application.rb:
Slim::Engine.set_default_options :pretty => true
Nevertheless, not only usage of rdiscount for posts rendering breaks all that beauty, but typical commands do that, e.g.:
title
= "#{t "title.main"} - #{(yield :title) || "#{t "title.default"}"}"
== stylesheet_link_tag "application", :media => "all"
turns into
<title>Some title</title><link href="/assets/application.css?body=1" media="all" rel="stylesheet" type="text/css" />
In additon, some examples of tags indentation:
<body>
<header>
<h1>...
</header>
<div class="content"><div class="posts"><article>
<div class="title">
<h3>...</h3>
<h2>...</h2>
</div>
<div class="entry"><p>...</p>
<p>...</p>
</div>
</article><article>
<div class="title">
<h3>...</h3>
<h2>...</h2>
</div>
<div class="entry"><p>...</p>
<p>...</p>
</div>
</article><article>
Maybe there is some after_filter or whatever exist to prettify responce.body after all?
That :pretty => true will be disabled then because it does only a half of the work.