Add Custom Default Places In Google Places AutoComplete - javascript

I want to make an input with autocomplete use google places API. And this is my code:
var options = {
componentRestrictions: {
country: "de"
}
};
var place = '';
var locationAutocompleteOneWay = document.getElementById('locationAutocompleteOneWay');
var autocompleteLocationOneWay = new google.maps.places.Autocomplete(locationAutocompleteOneWay, options);
google.maps.event.addListener(autocompleteLocationOneWay, 'place_changed', function() {
place = autocompleteLocationOneWay.getPlace();
});
For more customize, I want to add some custom place result when I input in the textbox. Here my code and result:
setTimeout(function() {
$(".pac-container").append('<div id="areasearch" class="pac-item areasearch"><span class="pac-icon pac-icon-areas"></span><span class="pac-item-query"><span class="pac-matched"></span>Test place</span> <span>custom place</span></div>');
}, 500);
But I want when I click on the result, it make my input locationAutocompleteOneWay has had a value of the result. But I don't know how to make it. And I want it can apply for multi-input on the page. I use it by jQuery and AngularJS. All solution of Jquery and AngularJS is good for me. Thank in advanced.

What I found is that, if you load the custom locations you're adding with attributes that can be used to set the lat/lng (and anything else you need), then you can bind to the mousedown event to assign a custom place object to the autocomplete.
In my script, I have the following snippet adding an item to the autocompletes (this adds to all auto-complete elements on the page):
$(".pac-container").append('<div id="areasearch' + i + '" class="pac-item areasearch custom" val="' + PlaceName + '" lat="' + Latitude + '" lng="' + Longitude + '" style="display: none;"><span class="pac-icon pac-icon-areas"></span><span class="pac-item-query"><span class="pac-matched"></span>' + PlaceName + '</span> <span>' + LocationName + '</span></div>');
Using the classes pac-item and custom, I then bind as follows:
setTimeout(function () {
$("div.pac-item.custom").mousedown(function () {
setCustomLocation($(this));
})
}, 100);
And the custom location function is:
setCustomLocation = function (obj) {
$("#" + currInput).val($(obj).attr("val"));
var newObj = {};
newObj["geometry"] = {}
newObj["geometry"]["location"] = {}
newObj["geometry"]["location"]["lat"] = function () { return $(obj).attr("lat"); }
newObj["geometry"]["location"]["lng"] = function () { return $(obj).attr("lng"); }
currAutocomplete.set("place", newObj);
}
The first line sets the name into the active input field, and the rest sets the place object for the active autocomplete (both variables captured in other events). The only values I needed for the project was the geometry lat/lng pair, but if you need more, just load it with whatever values you need to retrieve from the parent.

Related

Formatting jQuery Autocomplete to extend past browser/window edge like drop downs do

I'm trying to get auto complete to extend past the browsers bottom edge like drop downs do.
An example of what I'm talking about is here:
http://jsfiddle.net/3gre9q1f/5/ (updated to remove html tags in css per Twisty)
var aTags = [ "ActionScript",
"AppleScript" ...... ];
$( "#tags" ).autocomplete({
source: aTags
});
This is a naive example of invoking the auto complete but demonstrates the behavior.
The use case for this is that I have modal windows that the auto complete currently extends past the bottom of the window like the jsfiddle example does and makes it hard to select/see the auto complete options.
Drop Down extending past browser bottom frame
Edit:
I do have ajax data that I'm working with to populate the auto complete and I am limiting the return results.
The answer turned out to be to use a HTML5 Datalist instead of a jQuery autocomplete. Datalists render natively and pop out past browser windows. In my particular case it was a pop-up modal window where auto-complete was getting cut off.
Here's an example of DataList behavior that works like I want http://jsfiddle.net/3gre9q1f/7/
The big downside is that this approach doesn't currently work for Safari or the Native IOS browsers and the implementation is a bit clunky. You have to adjust the width of the datalist as well as sticking the value of the option in a javascript dictionary for future lookup because some browsers search against the option text and other browsers search against the option values thus breaking autocomplete.
So what I did was add a couple global variables:
var searchResultsDictionary = {};
var maxListLength = 200;
Then created an empty datalist in my form/page
<input type="text" list="searchList" id="search" placeholder="Search" required />
<datalist id="searchList" style="width:auto; position:relative;" ></datalist>
Then I populated it with an ajax call tied to input change on the text box
$("#search").on('input propertychange paste', function () {
var searchval = $("#search").val();
if (searchval != null && searchval.length > 1) {
LoadsearchResults(searchval);
}
});
function LoadsearchResults(searchFor) {
var url = "this.website.some.made.up";
$.ajax({
url: url,
data:
{
values: searchFor
},
dataType: 'json',
success: function (data) {
$("#searchList").empty();
var charwidth = 5.6;
$.map(data, function (item) {
// Add the <option> element to the <datalist>.
var innerOption = item.FirstElement + ' 1st ' + item.SecondElement + ' - 2nd# ';
var option = "<option data-value='" + item.SearchItemID + "'>" + innerOption + "</option>";
$("#searchList").append(option);
resultsDict[innerOption] = item.SearchItemID;
if (innerOption.length * charwidth > maxListLength) { maxListLength = innerOption.length * charwidth; }
});
if (maxListLength > 495) { maxListLength = 495; }
$("#search").css("width", (maxListLength + 5));
$("#search").focus();
$("#search").css("width", (maxListLength + 5));
},
error: function (xhr, textStatus, errorThrown) {
alert('Error: ' + xhr.responseText);
}
});
}
Then in the save/create/next step function I compared the text box value against the dictionary to come up with the ID of the item to do work against.
var searchId = ""; // search item to create
var labelLookfor = $("#search").val();
searchId = searchResultsDictionary[labelLookfor];
if (searchId != null && searchId.length > 0) {
//Here's where the Save/Next step would be called
}else{
alert("Search Lookup Not Found");
}

Calling Jquery accordion on google maps only runs once

So I've created a google maps page with a bunch of markers generated from XML. The idea is that when you click on a marker a div will be generated that displays events information related to that marker. This all works fine but what I'm struggling with is now trying to attach an accordion to the events information. The code I have so far will show an accordion on the first marker you click on (can be any one and it returns the correct info, shows the div and has an accordion) but not on any subsequent marker clicks, even the same one for a second click.
I'm sure this must be a simple fix but I've tried a few variations (there are three attempts at the accordion that I have left in to show the different versions) and I am getting the same results.
Here is the code that binds the events to the markers as a google event listener..
function bindEvents(marker, id, venueName, website){
google.maps.event.addListener(marker, 'click', function(){
// TARGET and show eventsFeed on click
$('#eventsFeed').show(222);
var eventsList = document.getElementById('eventsList');
// ADDS styles to the events feed divs when created
// DECLARED here for the inclusion of the venueName & website as feedhead
// even when no events are present
var venueNameDiv = "<div class='venueNameFeed'>";
var webSiteDiv = "<a target='_blank' class='websiteInFeed' href='http://"+website+"'><span class='fa fa-home'></span></a>";
var titleInFeed = "<div class='"+id+" eventTitleFeed'>";
var accordDataWrap = "<h2 class='accordWrap>";
var eventInFeed = "<div class='eventDescFeed'>";
var dateInFeed = '<div class="eventDateFeed">';
var priceInFeed = "<div class='eventPriceFeed'>";
// CLOSE the divs after each entry
var divBrk = "</div>";
var closeAccordDataWrap = "</h2>";
var feedHead = venueNameDiv + venueName + divBrk;
// EMPTY array to line up matched events in
var eventsLine = [];
// CYCLE through eventsArray
for (var key in eventsArray){
var eventLoop = eventsArray[key];
// MATCH id to venue_id
var venue_id = eventLoop.venue_id;
if (venue_id == id){
// ONLY show events from todays date onward
var now = new Date();
var date = new Date(eventLoop.eventDATE);
// SET hours to 0 to ignore time part (always as 01:00:00 for event date?)
now.setHours(0,0,0,0);
if (date >= now){
//ADD all matched events to eventsLine array
eventsLine.push(titleInFeed + eventLoop.eventTitle + divBrk +
accordDataWrap + eventInFeed + eventLoop.event + divBrk +
dateInFeed + formatDate(eventLoop.eventDATE) + divBrk +
priceInFeed + "£" + eventLoop.price + divBrk + closeAccordDataWrap);
}
}
}
// TURNS the array into a string and replaces those damned, infernal commas!!
var outputString = eventsLine.toString().replace(/>,/g, '>');
// PUT the compiled array into the eventsFeed div (with venueName as title)
if (website==""){
eventsList.innerHTML = feedHead + outputString;
} else {
eventsList.innerHTML = feedHead + webSiteDiv + outputString;
}
// ADD the accordion
$(document).on('click', marker, function(){
$(eventsList).accordion({
header: "div."+id,
icons: null
})
})
// OR
$(eventsList).each(function(){
$(eventsList).accordion({
header: "div."+id,
icons: null
});
});
// OR
accordion(eventsList, id);
});
}
This third option calls a separate function which is defined as;
function accordion(placement,id){
$(placement).accordion({
header: "div."+id,
icons: null
});
}
As you can probably tell I'm pretty new to all of this so any help or advice with anything would be greatly appreciated! :)
Can you replace this code:
$(eventsList).each(function(){
$(eventsList).accordion({
header: "div."+id,
icons: null
});
});
with this code:
$(eventsList).each(function(){
$(this).accordion({
header: "div."+id,
icons: null
});
});
and try. Also it will be better if you can Create a fiddle for your code.

Problems updating the content of a Kendo UI TabStrip without AJAX?

I have a small console that displayed the output of certain actions in my website, the need to have another console that would display a different kind of output made me want to combine both consoles in a Kendo UI TabStrip, the thing is that the information displayed on the console isn't received with AJAX so when I started to insert the HTML elements like before, the tab didn't got updated.
This is how I initialize the tab:
$('#tabConsole').kendoTabStrip({
animation: {
open: {
effects:'fadeIn'
}
}
});
This is how my HTML looks:
<div id="tabConsole">
<ul>
<li class="k-state-active">Salida</li>
<li id="notificacionTab">Notificaciones</li>
</ul>
<div id="userConsole"></div>
<div id="notificationConsole"></div>
</div>
This is how I try to update it:
function appendToConsole(content, type, optional) {
//code to append to console
var actualDate = new Date();
var prevContent = $('#userConsole').html();
if (typeof prevContent === 'undefined') {
prevContent = '';
}
var strType = '';
var iconType = '';
var moreOutput = '';
if (type == 1) {
strType = 'infoConsole';
iconType = 'infoIcon.png';
} else if (type == 2) {
strType = 'warningConsole';
iconType = 'warningIcon.png';
moreOutput = '<img id="viewDetails" value="' + optional + '" class="moreConsole" src="../Content/images/icons/arrow.png">';
} else if (type == 3) {
strType = 'errorConsole';
iconType = 'errorIcon.png';
}
var iconOutput = '<img class="iconConsole" src="../Content/images/icons/' + iconType + '">';
var dateOutput = '<div class="dateConsole">' + iconOutput + ' ' + actualDate.toLocaleDateString() + ', ' + actualDate.toLocaleTimeString() + ' : </div>';
var consoleOutput = prevContent + '<div class="outputConsole">' + dateOutput + content + moreOutput + '</div>';
$('#userConsole').html(consoleOutput.toString());
var height = $('#userConsole')[0].scrollHeight;
$('#userConsole').scrollTop(height);
//my try to update the tab
var tabStrip = $('#tabConsole'),
selectedIndex = tabStrip.data('kendoTabStrip').select().index(),
clone = original.clone(true);
clone.children('ul')
.children('li')
.eq(selectedIndex)
.addClass('k-state-active')
.end();
tabStrip.replaceWith(clone);
$('#tabConsole').kendoTabStrip({
animation: {
open: {
effects: 'fadeIn'
}
}
});
}
How can I update the contents of the DIV that are inside the TabStrip?
EDIT
It seems Kendo UI renames the DIVs' ids that represent the tabs to tabConsole-1 and tabConsole-2, explaining why the update wasn't working, still there's a lot of strange behavior, I had to specify the height for each DIV so the overflow propety would work, also the images with id viewDetails and class moreConsole when set to position absolute, get rendered outside the DIV that represents the tab, but if I change the position property to relative, the images stay inside the DIV but are displayed not at the end of the DIV like I want to, but relative to the size of the DIV that comes before them.
I'm really confused as to how to set the styles so the contents are displayed properly.
Adding content to a tabStrip can be achieved using:
$(tabConsole.contentElement(idx)).append(newContent)
where:
idx is the tab index,
newContent is what you want to add to the existing content and
tabConsole is the variable set to $("#...").kendoTabStrip(...).data("kendoTabStrip");.
You don't need to create a new tabStrip (in addition you should not re-create KendoUI elements since this is a pretty expensive operation).
About using multiple tags with the same id... you should not use it, use class instead. ids should be unique.
I'm still trying to understand your problem with the styling.

jquery event no change

The is(:focus) was the aproach. The final code is listed below:
setInterval(function(){
if($j("SELECT[name='cf20_field_7']").is(":focus")) return false;
var information = '';
var i = 1;
$j("#cf20_field_1").html();
//add new information to hidden field
$j("#cforms20form .info_for_email").each(function(){
var name = $j(this).find("INPUT[name='cf20_field_5']").val();
var inn = $j(this).find("INPUT[name='cf20_field_6']").val();
var view = $j(this).find("SELECT[name='cf20_field_7']").val();
//render
information += i + ")";
information += "Наименование организации: " + name + ".<br/>\n";
information += "Реквизиты организации: " + inn + ".<br/>\n";
information += "Стоимость заказа: выписка " + view + ".<br/>\n";
i++;
})
$j("#cf20_field_1").html(information);
hovered = true;
}
,100
);
Is there some possibility to fire function when there is no hover in SELECT field.
And also there may be aproach that to check is there is no hover on SELECT field.
It cause problemms. When you are trying to select another option cursor is begging while setInterval is working.
The best approach that i find is listed below:
//every 100 mil secconds update info
setInterval(function(){
$j("SELECT[name='cf20_field_7']").trigger('change');
if ( $j("SELECT[name='cf20_field_7']").on("change")) return false;
var information = '';
var i = 1;
$j("#cf20_field_1").html();
//add new information to hidden field
$j("#cforms20form .info_for_email").each(function(){
var name = $j(this).find("INPUT[name='cf20_field_5']").val();
var inn = $j(this).find("INPUT[name='cf20_field_6']").val();
var view = $j(this).find("SELECT[name='cf20_field_7']").attr("value");
//render
information += i + ")";
information += "Наименование организации: " + name + ".<br/>\n";
information += "Реквизиты организации: " + inn + ".<br/>\n";
information += "Стоимость заказа: выписка " + view + ".<br/>\n";
i++;
})
$j("#cf20_field_1").html(information);
}
,100
);
More information:
I can discribe situation more. So i had a form. onsubmit event didn`t work because there is another event is attachet. So i deside to update value of first field of form every 100 milisecs. The value is containing all dynamictly created "selects and inputs". But when i try to change value of the select by mouse. The function is fired and function check value of select and cause mouse begging. So i need somehow to check if that select is hovered to prevent firing of the function.
Invalid here:
if ( SELECT[name='cf20_field_7'].on("change"))
I guess you need this:
if ( $("SELECT[name='cf20_field_7']").on("change"))
But still, the above is invalid. You need some handler like:
$("SELECT[name='cf20_field_7']").on("change", function(){
return false;
});
if ($j("SELECT[name='cf20_field_7']").on("change")) return false
Not clear what should be checked here. I assume you want to run some function attached to onchange even of select. In that case you should use .trigger instead of .on. But in both cases return value will be jquery object (for chaining purposes) so basically your statement will always be true both with trigger and on If you want to test some value of select, you should do something like next:
if(someTestFunct($j("SELECT[name='cf20_field_7']"))) return false;
function someTestFunct(jObj) {
//some other code?
return jObj.val() == "some value to test";
}
Possibly some better approach may be used, but without more details it is hard to suggest something.

Sidebar and tabbed info windows using google maps v2

Does anyone know of an example where a Google Map is used to create a map with both a sidebar
http://econym.org.uk/gmap/example_map4c.htm
and tabbed info windows
http://econym.org.uk/gmap/example_map10a.htm?
The markers are defined and ready for sidebar
function createMarker(point,name,html) {
var marker = new GMarker(point,{icon:myIcon});
// add a line to the side_bar html
side_bar_html += '<div id="'+linkid+'"><a href="javascript:myclick(' + (gmarkers.length-1) + ')">' + name + '<\/a><br><\/div>';
return marker;
}
The sidebar gets its titles from the 'name' defined for the marker :
var marker = createMarker(point,"Point Title", 'Point Content')
map.addOverlay(marker);
Tabs are generated by passing the markers into arrays :
function createTabbedMarker(point,htmls,labels) {
var marker = new GMarker(point);
and
var marker = createTabbedMarker(point, ["Tab 1 contents", "Tab 2 contents","Tab 3 contents","Tab 4 contents"],["One","Two","Three","Four"]);
map.addOverlay(marker);
My question is how can I grab just the first part of the array [labels], in this example 'One', and have that be what the output is for the sidebar ?
The sidebar in the first example is not a feature of the Google Maps API; i's just a table cell which is updated in Javascript.
It is doable ... if you check the Google Maps documentation on Gmarker, or more specifically Gmarker.openInfoWindowTabsHtml, you will see that it takes two arguments:
An array of GInfoWindowTab's
A GInfoWindowOptions javascript object.
In the documentation for GInfoWindowOptions you will see that you can pass in the tab index via the selectedTab property. In that case, we can use the code from the sidebar example and simply update the myclick function:
function myclick(i) {
gmarkers[i].openInfoWindowHtml(htmls[i]);
}
becomes:
function myclick(i, tab_index) {
gmarkers[i].openInfoWindowHtml(htmls[i], { selectedTab : tab_index });
}
And we update the createMarker function to accept the number of tabs this marker should have:
createMarker(point,name,html,tab_count) {
// ...snip ...
var links_html_temp = "";
while (--tab_count) {
links_html_temp = '<a href="javascript:myclick(' + i + ',' + tab_count + ')">' + name + ': Tab #' + tab_count + '<\/a><br>' + links_html_temp;
}
side_bar_html += links_html_temp;
I'll leave it to your own specific implementation to pass the appropriate tab count to createMarker.

Categories