Locations area map with jQuery load function importing external HTML - javascript

I have a US HTML image map with the states highlighted with coordinates. Each state when clicked will bring up a modal window with facilities locations.
Right now I have it where each state has an ID, the user clicks on the hotspot and then it loads the facilities locations with external HTML via jQuery .load() to lighten the document load.
Here's an example in the JS
$('#Alabama').load('locations/Alabama.html');
and then the container that will load Alabama html in the main document is
<div class="overlay" id="Alabama"></div>
As you can see I have to enter these in for each state. Obviously this is tedious and probably not the best method. DRY comes to mind but I'm not good at writing Javascript from the ground up.
What would be the best way to access the state IDs without writing each state instance? I'm thinking a JSON object with a click function that constructs the markup and calls the modal window. I'm just not sure where to begin.

If it's a modal window, then you could probably just use the same overlay each time a state is clicked. So basically just do this...
$(".overlay").load("locations/alabama.html");
A full example might look something more like this though...
$("area").click(function(){
var url = $(this).attr("href");
$(".overlay").load(url);
});
You may have to do something to prevent the browser default behavior of navigating on the clicked area. You could remove the href values and put them somewhere else...
$("area").each(function(i, area){
$(area).data("old-href", $(area).attr("href");
$(area).attr("href","#");
});
//Then you do the same as above, but you get your url from the data method.
$("area").click(function(){
var url = $(this).data("old-href");
$(".overlay").load(url);
});

Related

Problems when combining css :target selector with url hash parameters for showing a modal

My javascript and css knowledge is rather limited. I think I am missing some subtleties of when and how css is applied as well as how page loading, combined with asynchronous javascript, calls works.
This is working:
I have a css only modal which displays when the id of my modal (view) matches the hash in the url (#view). I use it to display images (it is the same modal div for all images and the actual image src is updated via event listeners added to links to the modals' anchor). This is working fine.
This is working:
I wanted to extend this so I could directly link to an already open popup by providing the url as a hash parameter. I.e. example.com/#view=imageUrl. Just opening this will not make the css selector :target match, since it now contains the view, but if I split this off by checking var hash = window.location.hash.substr(1); I can separate the url from the anchor and if I then use:
window.history.pushState("", "", window.location.href.split('=')[0]);
updateModal(imageUrl)
where updateModal sets the source of the image to the split off url. All is fine, too, i.e. the site opens with the modal open and the image from the url in there.
This is not working:
Now I thought, it is possible that the image provided as hash parameter does not exist anymore, so I only want to show the modal if there is a valid image provided, otherwise go to the main page. I created a dummy image element, try loading the image from imageUrl and move the splitting and updating bits to the onload method of the dummy image, like so:
dummyImage.onload = function () {
window.history.pushState("", "", window.location.href.split('=')[0])
updateModal(imageUrl)
}
If I do this, the modal does not show. The css does not get applied, why is this?
I also tried changing the visibility of the modal myself:
dummyImage.onload = function () {
window.history.pushState("", "", window.location.href.split('=')[0])
updateModal(imageUrl)
var myModal = document.getElementById('view')
myModal.style.display = 'flex'
myModal.style.visibility = 'visible'
}
Which makes the modal appear, but seems to add a style that cannot be overridden by the css anymore. Specifically, when I click the close link of the modal which just goes to a different anchor #noname the url changes, the css :target selector should not match anymore, but the modal does not close anymore. Why would the css not apply anymore?
Reading the below links, I believe this is a bug and that, on changing the url with pushState, the :target selector is not re-evaluated after page load. I will work around this by always showing the modal, as in the second working example in the question and use a fall-back image and message to alert the users that the image is no longer available (I can trigger this update with dummyImage.onerror).
https://bugs.webkit.org/show_bug.cgi?id=83490
https://css-tricks.com/on-target/
https://github.com/ReactTraining/history/issues/503
https://github.com/whatwg/html/issues/639
If anybody knows a better solution or workaround, I am still interested to learn!

Event firing one page affecting another page

I have two pages, say page1.jsp and page2.jsp and a common javascript file script.js.
I have an onclick call in page1.jsp like this:
<td>004</td>
and this method is in script.js defined as:
<script>
function onTab_ServiceTypes() {
// Here I want to hide a div of page2.jsp, like this
$("#div_of_page2JSP").hide();
}
</script>
How can I do this?
you can't do that if both pages are independent(page2 is loaded via a page reload).
What you can do is to store the clicked state using a cookie/web-storage(local storage/session storage) then when the second pages is loaded check the state of the stored value and then hide/show those elements.
If I understand your question right this is not possible. You won't be able to manipulate elements not within the current DOM with JavaScript. You could probably pass a variable in your URL like page2.jsp?hideDiv=true (You would have a better name for this variable...) when you click the link and navigate to page2.jsp and hide div on page load.

Appending AJAX loader to menu/nav bar on individual links

I'm using the following theme for our site: http://themes.vivantdesigns.com/vpad/#dashboard.html
I want an ajax loader to show NEXT to the link/tab, when a user clicks a link within the drilldown menu on the left. As you can see from the link, content is dynamically loaded within a:
<section id="main-section">Pagename.html loaded here</section>
So basically, I want the ajax loader to show to the right of the menu links and disappear when the dynamic content loads. It will be hard to see this pause on the demo link, but heavier database queries will cause it to sit there a moment, and slower connections of course.
Any immediate help is appreciated very much.
I've tried show/hide onClick methods, hiding class on document ready, and nothing seems to work cleanly.
Okay, after a lot of screwing around trying to find where the ajax was happening, I think I've worked it out (little familiarity with jQuery/never heard of hashchange or bbq before), so give this a shot.
Assuming you have access to it, the page you referenced is including a JavaScript file called global.js.
Add an initially hidden "loading" image/div/whatever next to each menu item, with an id set similarly to the menu item's name e.g. id="mediaLoading".
Open global.js and head down to line 117:
$('#'+id).length && $('#'+id).remove();
After this line the ajax call is made, so add the code to show the ajax loader, e.g.
var loaderId = h.replace(/^\#/, "") + "Loading";
document.getElementById(loaderId).style.display = 'block';
//or $("#" + loaderId).show() or whatever you would use in jQuery
Finally, to re-hide it, add similar code into the inline 'complete' function (which would now be around line 127):
complete: function(jqXHR, textStatus) {
document.getElementById(loaderId).style.display = 'none';
}
Hope that solves it. It was difficult to test locally.
Keep in mind that since the file's called "global," that obviously might impact a bunch of other pages, so you may want to use null-checks for the loader or a separate file...

Change Page for jQuery Mobile between two html files

I'm trying to make a simple site with two pages, "Search" and "Results".
At first, I had a multi-page template working fairly well. I would change the page, and on page change I would use ajax to get the results. The problem was that I wanted to be able to load the results page without first going back to the search page.
I want to pass parameters to the results page via the querystring so that I can have something like this:
search.html + "some search terms" -> results.html?q=some+search+terms
The problem is that I can't seem to get anything to work right when I split up the html into two files.
I try calling
$.mobile.changePage("results.html?q=" + escape(search))
on the search page, but the $(document).ready function is not firing. I kind of get why it doesn't, since changePage is loading the second page into the DOM?
I also tried manually redirecting, in which case the $(document).ready function does fire on results.html, but using the back button or going back to the search page doesn't fire THAT $(document).ready.
I tried wiring up the pagechange function to search.html, assuming that this would fire when I load the second page, but nothing happened.
Does anyone have suggestions as to how I would pull this off? Or the best way to get the results page to act more independent of the search page?
I've been bitten by this too, it really isn't a good idea to pass parameters through the query string and it makes jQueryMobile behave in an odd way.
Instead I've been using sessionStorage which works perfectly. You could also use a cookie.
I'm not 100% sure where you're actually having issues, but here is some important jQuery Mobile specific info that can help you.
First, read the big yellow section at the top of this page: http://jquerymobile.com/demos/1.1.0/docs/api/events.html
document.ready does not fire when a page is brought into the DOM from an external document. Instead you need to use event delegation and the page-events specified in the link above. Most likely you want to use pageinit as a replacement for document.ready.
Then read the top section of this page: http://jquerymobile.com/demos/1.1.0/docs/api/methods.html (the part about $.mobile.changePage()).
The important part about the second link is that you can pass data via the $.mobile.changePage() function like so:
$.mobile.changePage('results.html', { data : { q : search } });
You can even set the type option to post so there will not be a query-string sent (this should ensure you don't get multiple of the same page in the DOM at a time).
$.mobile.changePage('results.html', { data : { q : search }, type : 'post' });
Another fix would be to manually add the data-url attribute to the <div data-role="page" id="results"> page. When you grab a page like this:
$.mobile.changePage("results.html?q=search+term+here");
It's data-url gets set to: results.html?q=search+term+here. If you manually set the data-url to results.html then you can navigate to the page like this:
$.mobile.changePage("results.html", { data : { q : 'search+term+here' } });
Which will look first for the data-role="page" element that has the data-url attribute set to results.html before re-loading the pseudo-page via AJAX.
Thanks for the input guys. I used a plugin that allows me to use faux-query parameters in the hash for a multi-page layout.
https://github.com/jblas/jquery-mobile-plugins/tree/master/page-params
I just added this in and ran the search on page change, getting those page parameters for the search.

Prefixing a URL in an window.open function jQuery

I have this HTML:
Track Your Package »
Somebody on this site was able to provide me with a script to prefix the URL with the domain http://www.example.com/ Here's the script:
$(document).ready(function(){
$('a[onclick^="window.open(\'TrackPackage.asp"]').attr('onClick', $('a[onclick^="window.open(\'TrackPackage.asp"]').attr('onClick').replace("window.open('", "window.open('http://www.example.com/"));
});
However, I am having a little trouble with this:
The first issue is where there is multiple instances of the element. Here's a fiddle: http://jsfiddle.net/VMmZx/
Instead of one anchor being signed with ID=4 and the other with ID=5 as intended, they're both being signed with ID=4.
The idea is, each window.open function should be prefixed with http://www.example.com however, the remainder of the URL should remain intact...
The second problem I'm encountering is when the element does not exist on a page, the remainder of the jQuery fails...
Here's another fiddle: http://jsfiddle.net/VPf32/
The <a> should get the class foo, but since the element does not exist on the page, the jQuery does not execute.
Since the JavaScript is being included in the HTML template of the ASP.NET server, this can create many problems.
I hope I've been clear and you can help me. Thanks.
You can use .each() to iterate over each matching element and change them individually:
$('a[onclick^="window.open(\'TrackPackage.asp"]').each(function(index, element) {
element = $(element);
element.attr('onclick', element.attr('onclick').replace(/open\('/, 'open(\'http://www.example.com/'));
});​
However, I don't think using links with a href of # and an onclick opening a window is as semantic as it could be. If possible, try changing the markup to this:
Track Your Package »
Now if someone is curious where it will lead them, the browser can show something useful in the status bar when you hover over it.
If you need to adjust the behavior further, add a class and bind for the click event. When they click, prevent the default action and open the window yourself, as you did before.
Why are you doing the click even inline like that? I would just output the links like:
Link Text
And then:
$('a[target=_blank]').click(function(){
var prefix = 'http://domain.com';
window.open(prefix + $(this).attr('href'));
});

Categories

Resources