Calling Jquery accordion on google maps only runs once - javascript

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.

Related

InfiniteScroll - How to reset all grid?

I am using InfiniteScroll:
var infScroll = new InfiniteScroll( '.grid', {
path: function() {
var pageNumber = ( this.loadCount + 1 );
var apiUrlQuery = $('.pagination__next').attr('href') + '&page=' + pageNumber;
return apiUrlQuery;
},
responseType: 'text',
status: '.scroll-status',
history: false
});
But now I need to implement search, so that means I need to refresh the path and the grid. How to do it?
So far what I have done is:
$('.search-events').on('click', function() {
infScroll.destroy();
/* building search query */
$('.grid-item').remove(); //Remove items visually from the grid
var apiUrlQuery = baseUrl + "&" + searchBy + "=" + searchTerm;
$('.pagination__next').attr('href', apiUrlQuery); //Update search url
infScroll.create();
infScroll.isLoading = false;
infScroll.loadNextPage();
})
With this, I am doing a new request using a new URL and get results but they don't get printed on the screen, also I see that the height of the grid is still the same as if I did not remove the grid-items.
Any ideas?
I finally made it work:
$('.search-events').on('click', function() {
msnry.remove($('.grid').find('.grid-item'));
var apiUrlQuery = baseUrl + "&" + searchBy + "=" + searchTerm;
$('.pagination__next').attr('href', apiUrlQuery);
infScroll.isLoading = false;
infScroll.canLoad = true;
infScroll.create();
msnry.layout();
infScroll.loadNextPage();
})
This line removes the elements from the DOM as I did with $('.grid-item').remove(), but also remove it from some internal array that keeps data.
msnry.remove($('.grid').find('.grid-item'));
Also, I removed infScroll.destroy(); because it unbinds from the load method.
The key part is msnry.layout(); this one rebuilds the layout.
Hope it helps someone in the future.

How to create a toggle button that dynamically changes HTML content?

I have been working on this question for several days, and have researched it on SO as well as the web at large and was unable to find material that helped me solve it.
I am trying to create a weather app that can toggle the weather units displayed between Fahrenheit and Celsius. I start by appending the weather in Fahrenheit, and then I have created an event handler that conditionally changes the inner content of the associated element based on whether that element is currently displaying "F" or "C".
As it is, my app successfully loads with the Fahrenheit temperature, and toggles to Celsius on click, but it will not toggle back to Fahrenheit. I assume there is some issue with how the events are registered, but for the life of me I cannot figure it out.
Here is my code:
var fahr = document.createElement("a");
fahr.attr = ("href", "#");
fahr.className = "tempUnit";
fahr.innerHTML = tempf + "°F" + "<br/>";
$("#currentWeather").append(fahr);
var cels = document.createElement("a");
cels.attr = ("href", "#");
cels.className = "tempUnit";
cels.innerHTML = tempc + "°C" + "<br/>";
var units = document.getElementsByClassName("tempUnit");
$(".tempUnit").click(function() {
if (units[0].innerHTML.indexOf("F") != -1) {
$(".tempUnit").replaceWith(cels);
} else {
$(".tempUnit").replaceWith(fahr);
}
})
Thank you so much in advance! Happy to provide additional information if necessary.
Currently what you are using is called a direct binding which will only attach to element that exist on the page at the time your code makes the event binding call.
As you using replaceWith(), existing element is replaced with new element and event handlers are not attached with them.
You need to use Event Delegation using .on() delegated-events approach.
General Syntax
$(parentStaticContainer).on('event','selector',callback_function)
Example, Also use this i.e. current element context and use setAttribute() to update href element
$("#currentWeather").on("click", ".tempUnit", function() {
if (this.innerHTML.indexOf("F") != -1) {
$(this).replaceWith(cels);
}
else {
$(this).replaceWith(fahr);
}
})
var tempf = 212;
var tempc = 100;
var fahr = document.createElement("a");
fahr.setAttribute("href", "#");
fahr.className = "tempUnit";
fahr.innerHTML = tempf + "°F" + "<br/>";
$("#currentWeather").append(fahr);
var cels = document.createElement("a");
cels.setAttribute("href", "#");
cels.className = "tempUnit";
cels.innerHTML = tempc + "°C" + "<br/>";
$("#currentWeather").on("click", ".tempUnit", function() {
if (this.innerHTML.indexOf("F") != -1) {
$(this).replaceWith(cels);
} else {
$(this).replaceWith(fahr);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="currentWeather"></div>

Add Custom Default Places In Google Places AutoComplete

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.

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.

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