Cannot use Bootstrap collapse functionality with Angular routing - javascript

UPDATE #2: I've implemented a button and UI Bootstrap and got the menu functioning without Angular Routing taking over, however, I can't get the menu to collapse after selecting a menu item and rerouting.
UPDATE: As per the suggestion, I've updated the above listener to this (to no effect):
$('a:not([data-toggle="collapse"])').click(function (e) {
var url = $(e.currentTarget).attr('href') || '#';
if (!(url.charAt(0) == '#')) {
window.location.href = url;
}
});
All of the Angular code for this app seems to be in js/compiled.min.js - if something is wrong, surely it'd start here, right?
I have inherited some work from a previous developer that has some funky code which is causing me a bit of a headache. If you visit http://www.executionists.com/#/ in Chrome and change the viewport to a mobile device, you'll see that the menu doesn't work as it does when it's in a larger viewport.
When you click the menu button Angular tries to route the page which of course results in a 404. I cannot for the life of me figure out why it's trying to route and how to prevent it. Things that I've tried.
Using UI Bootstrap in the manner listed here (under Collapse section): http://angular-ui.github.io/bootstrap/
One thing to note is that I had to put the following fix in place to fix another bug where angular routing was not allowing for browser history to function. A common problem, I have discovered. When I put the fix in place, routing and history function as desired for the entire site, however, I am suspicious of this being the cause of my mobile-friendly collapsible menu bug. The fix:
// This is required for links to work properly with the browser history
$('[ng-app]').on('click', 'a', function() {
window.location.href = $(this).attr('href');
});
I don't know what to do about this or even how to best diagnose the issue.

You are targeting all links with that listener, perhaps be more specific:
$('a:not([data-toggle="collapse"])').click(function (e) {
var url = $(e.currentTarget).attr('href') || '#';
if (!(url.charAt(0) == '#')) {
window.location.href = url;
}
});

Related

How to keep elements non-refreshed

The main goal is to keep non-refreshed the logotext <div class="small-7 medium-4 columns logo"> and the menu <nav class="pagedMenu" role="navigation">,without clipping on page refresh or while the content is loading from a page to another. Also, the menu state should be preserved from a page to another.
I've found here a possible solution that could solve the problem (you could use ajax to fetch the updated content and use jQuery to put the new content on the page and avoid the refresh entirely. Doing it that way, the existing data in the page would remain untouched. said #jfriend00)
So, I have tried to use an Ajax plugin (called AWS). In the AWS option page, I (suppose) that I've done the right thing pointing wrapper as Ajax container ID and also pagedMenu as Menu container class, Transition Effect Enabled, No ajax container IDs blank, no loader selected, having already a pulse loader implemented in the theme.
At this point, all I got it's a menu / side-menu (shiftnav) / pulse dot loader / content loading malfunction, generated perhaps by the wrong defined Ajax container id and/or menu container class(?) OR by a conflict with an existing JS / jQuery code, not so sure.
Also in Chrome console there is an error:
Uncaught SyntaxError: Unexpected token ;
(anonymous function) # ajaxify.js?ver=4.3.1:175
n.extend.each # jquery-2.1.4.min.js?ver=2.1.4:2
n.fn.n.each # jquery-2.1.4.min.js?ver=2.1.4:2
$.bind.$.ajax.success # ajaxify.js?ver=4.3.1:169
n.Callbacks.j # jquery-2.1.4.min.js?ver=2.1.4:2
n.Callbacks.k.fireWith # jquery-2.1.4.min.js?ver=2.1.4:2
x # jquery-2.1.4.min.js?ver=2.1.4:4
n.ajaxTransport.k.cors.a.crossDomain.send.b # jquery-2.1.4.min.js?ver=2.1.4:4
Everything is getting back to normal on page refresh but doesn't help at all, being useless.
I also have to mention that for the menu I've tried to keep the state using jQuery-Storage-API and storage=jQuery.sessionStorage; as you can see in mynewmenu.js file but that will not solve the non-refreshing elements problem.
The menu jsfiddle only, if this helps to have the whole picture, here thanks to #Diego Betto.
You can use this live link as example; there is a similar situation with the above described - Ajax implementation right(?) - and regarding the appearance, menu is kept non-refreshed from one page to another; if you browse Books, Works etc, menu sections you'll see; if there is a model that could be implemented here, I'll be glad to find it.
LE: meanwhile, I've tried another ajaxify solution made by #arvgta - special thanks - without success yet but as far as I've found from the Author, the defined elements should be div's with id's not classes. So, I'll try to find a way to modify somehow the code in order to have id instead on classes.
Also, I'll try to transform and implement in ajaxify.min.js file, the page-container element; jQuery('#page-container').ajaxify(); I'll come back with news.
LE2: I've tried to implement the solution using id's instead of classes but still, the pages are not loading correctly.
At this point we have ajax.min.js file updated with these lines:
(function($){
jQuery(document).ready(function(){
jQuery('#page-container').ajaxify({requestDelay:400,forms:false});
});
})(jQuery);
Also, I've modified the theme file to have id=page-container instead if class=page-container.
In these conditions, on menu click, the links are changed (like it should), menu/ logotext elements seems to working almost fine (sometimes get skippy changing position), but the content is not loading correctly in all cases; Same here, everything is getting back to normal on manual page refresh (f5), but doesn't help.
LE3: It looks like the conflict is (at least) between Revolution Slider plugin and Ajaxify.
errormessage="Revolution Slider Error: You have some jquery.js library include that comes after the revolution files js include." ;="" +=" This includes make eliminates the revolution slider libraries, and make it not work." "<="" span="">"
Site live link here. Any thoughts / alternative in this area? (not interested in using other different platforms, different WordPress themes, etc. just a workaround in this existing situation)
LE4: As far as I can see, there are many users that voted up the Jake Bown answer that could be indeed a solution; but I can't find the reason that didn't work correctly implemented into my theme (without errors) live link here The elements logotext / menu are still fading on refresh, are not kept non-refreshed. Any thoughts #Jake Bown / anyone?
LE final.
Buzinas delivered the closest answer for my needs, taking in consideration my site environment (plugins installed, etc).
From what you said I think I might have found the solution you're looking for - you want to load content dynamically whilst keeping the logo and navigation untouched? If so, this might be what you're looking for.
In the example, the pages are loaded in from a div within the page but could be used to load another URL or file:
$('.viewport ul li a').on('click', function(e) {
e.preventDefault();
var link = this.hash.substring(1, this.hash.length);
if($('.'+link).length) {
$('.viewport span.body').html($('.'+link).html());
}
});
TL;DR
I've created a plunker for you, take a look, and play with it as long as you can. You'll learn a lot from it!
I think you're trying too many things here, but didn't try the simplest:
The main goal is to keep non-refreshed the logotext and the menu ,without clipping on page refresh or while the content is loading from a page to another. Also the menu state should be preserved from a page to another.
If you want to do that, there are a few steps:
Create a 'master' page, that we're going to call index.html from now on.
So, our index must have the static part of our page, e.g menu, logo, footer etc.
Then, our 'subpages' must be cut down (no html, head, body, script, style tags, only the content that should be showed into our master page).
That done, now we must change our links to use AJAX instead of doing full refresh:
/* we add a 'click' event handler to our menu */
document.getElementById('menu-menu-2').addEventListener('click', function(e) {
var el = e.target;
/* then, we see if the element that was clicked is a anchor */
if (el.tagName === 'A') {
/* we prevent the default functionality of the anchor (i.e redirect to the page) */
e.preventDefault();
/* we show our spinner, so the user can see that something is loading */
spinner.classList.remove('hidden');
/* and we call our AJAX function, passing a function as the callback */
ajax(el.href, function(xhr) {
/* we get our main div, and we replace its HTML to the response that came
from the AJAX request */
document.getElementById('main').innerHTML = xhr.responseText;
/* since the request was finished, we hide our spinner again */
spinner.classList.add('hidden');
});
}
});
Ok, now our pages are already working via AJAX, and not reloading our static content.
But now, we see that we have some issues. For example, if someone tries to open one of our pages directly via URL, he'll see unstyled page, without the menu/logo etc. So, what should we do?
We have a few more steps now:
Simulate that our links are effectively transfering between pages using the History API:
/* inside our ajax callback, we save the fake-redirect we made into the pushState */
ajax(el.href, function(xhr) {
document.getElementById('main').innerHTML = xhr.responseText;
/* save the new html, so when the user uses the back button, we can load it again */
history.pushState({
html: main.innerHTML,
title: el.textContent + '| neuegrid'
}, '', el.href);
/* (...) */
});
/* and outside it, we add a 'popstate' event handler */
window.addEventListener('popstate', function(e) {
/* so, if we've saved the state before, we can restore it now */
if (e.state) {
document.getElementById('main').innerHTML = e.state.html;
document.title = e.state.title;
}
});
And we need that when the user enters directly to another page, e.g about-us, we redirect him to the index.html, and then load the about-us page from there.
So we create a redirect.js file, and we reference it in all of our
subpages:
/* save the page that the user tried to load into the sessionStorage */
sessionStorage.setItem('page', location.pathname);
/* and them, we redirect him to our main page */
location.replace('/');
And then, in our index.html page, we see if there is any page in the sessionStorage, and we load it, if there is, otherwise we load our home page.
var page = sessionStorage.getItem('page') || 'home';
/* we look into the menu items, and find which has an href attribute
ending with the page's URL we wanna load */
document.querySelector('#menu-menu-2 > li > a[href$="' + page + '"').click();
And that's it, we're done now. Take a look at the plunker I've been making to you.
And play with it as long as you can, so you'll learn a lot from it.
I hope I could help you! :)
Note: Just for reference, this is our ajax function:
function ajax(url, callback, method, params) {
if (!method) method = 'GET';
var xhr = new XMLHttpRequest();
xhr.open(method, url);
if (callback) xhr.addEventListener('load', function() {
callback.call(this, xhr);
});
if (params) {
params = Object.keys(params).map(function(key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');
xhr.send(params);
} else {
xhr.send();
}
}
GOING AJAXED WITH WORDPRESS
demo: http://so.devilmaycode.it/how-to-keep-elements-non-refreshed/
follow these simple steps (let's take as example theme "twentyfifteen" on the WP templates folder):
edit single.php, page.php, index.php and all other pages having get_header() and get_footer() functions and replace it respectively with below code:
NOTE: this is important because if someone (ex: search-engine) reach your pages directly from the link, it is still fully available and 100% working. (useful for SEO)
<?php
//get_header()
if(!isset($_REQUEST['ajax'])){
get_header();
}
?>
<!-- other code --->
<?php
//get_footer()
if(!isset($_REQUEST['ajax'])){
get_footer();
}
?>
open the header.php add the below code inside the <head> section at the very end
<script>
!(function($) {
$(function() {
$('.menu-item a, .widget-area a, .page_item a').on('click', function(e) {
e.preventDefault();
var href = this.href;
var query = href ? (href + (!/\?/g.test(href) ? '?' : '&') + 'ajax=1') : window.location;
/* IMPLEMENT SOME LOGIG HERE BEFORE PAGE LOAD */
/* ex: kill instance of running plugins */
$('#content').hide().empty().load(query, function() {
/* IMPLEMENT SOME LOGIG HERE AFTER PAGE IS LOADED */
/* ex: refresh or run a new plugin instance for this page */
jQuery(this).show();
});
});
});
})(jQuery);
</script>
in the header.php file put the code below at the end of the file, 90% of times you need it under the navigation. In this case we already have this on the "twentyfifteen" theme.
NB: most probably you have the opening tag <div id="content" class="site-content"> inside the header.php file and the closing tag </div> on the footer.php file, this doesn't matter, you can leave it as is.
<div id="content"></div>
NOTE: consider this a proof of concept; it may work as is, but you still need to tailor it to suit your needs; you may need to:
Add a menu (in case it is not already set) by going under Appeareace > Menus > [check Primary Menu] > Save Menu in order to activate the menu. it's tested and working.
You may want to add some other class to the jQuery function like .widget-area a in order to ajax also widget links.
if you are using 3d party plugins you may need to ensure that all dependencies of each plugin are loaded also on the main page from where you want everything is displayed without refreshing content.
you may need to check and kill those 3d party plugin before a new page load and run or refresh plugin needed in the loaded page.

Load external page on div and getting a specific url at the same time

I am developing a new website and while I want to get it done as easy to navigate as possible, I also wanted to use some kind of navegation with overlapping pages.
My idea was to have articles on the current page that will open on a floating div over the rest when clicked. That´s not really the problem because using jquery .load() it gets quite easy to do, but my problem is that it doesn't modify the current url, so it remains as www.myweb.com for example and I would like to have it like www.myweb.com/current-article when the article is opened. Once you have that specific url to the article, if it is shared, whoever open that link will get to the website with the article opened over the it.
I hope it all makes sense, but a good example can be found in USA Today or Play.Spotify
I am using umbraco 7 and javascript for the site. Any idea of how it could be done?
its called hash base navigation
location.hash = "#myHash"; //sets the url plus hash
Below is fired if user manually changes the URL or by using the back button
window.onhashchange = function()
{
if (location.hash === "#myHash")
{
doSomething();
}
}
This is actually a big and complex task to implement correctly.
I would advise you to use Backbone.Router http://backbonejs.org/#Router. It use history api in "new" browsers, with a fallback to hashtags in older browsers.
Some pseudo code:
First define your route. It will catch all pages under www.myweb.com/articles/*
var MyRouter = Backbone.Router.extend({
routes: {
"articles/:page": "loadPage"
},
loadPage: function() {
var div = $("#overlay");
div.html($.load("your page"))
div.show()
}
});
You would need to implement some logic to test if the loaded page is not under articles/.*
Init MyRouter when the page is loaded:
var router = new MyRouter();
router.start()
The overlay page will now open when you hit www.myweb.com/articles/cool-article
If you want to open the page from a parent page, simply call
$("button").click(function(){
router.navigate("articles/cool-article", {trigger: true});
});

How do I change this JavaScript?

I want to change the way that content is displayed on my website:
var FNav = {
init: function() {
$("a[href*=#]").click(function(e) {
e.preventDefault();
if($(this).attr("href").split("#")[1]) {
FluidNav.goTo($(this).attr("href").split("#")[1]);
}
});
this.goTo("home");
},
goTo: function(page) {
var next_page = $("#"+page);
var nav_item = $('nav ul li a[href=#'+page+']');
$(".page").fadeOut(500);
next_page.fadeIn(500);
How do I change this JavaScript, so I can have a proper back button functionality?
What I have tried (Unsuccessfuly). These are the solutions that I tried but without changing the javascript above. That is why I think none of them seem to work.
Using the History.js method described here:
https://github.com/browserstate/history.js/ I fill out all the steps and
enter the scripts to the header, however only the URL in the URL bar
changes when I click on a link. When I click the Back button, the URl
changes accordingly, but content doesn't load. When I enter a URL in
the URL bar, I get sent to the home page.
Ajaxify and Gist method
described here: https://github.com/browserstate/ajaxify Achieves the
same as above, same issues as well
Davis.js method described here:
https://github.com/olivernn/davis.js Achieves nothing upon completion
of the installation instructions. No change.
jQuery BBQ Plugin method
described here: http://benalman.com/projects/jquery-bbq-plugin/
Achieves nothing, no change upon loading the .js file in the header
of the website.
I read this article and understood it:
http://diveintohtml5.info/history.html
I'm not sure why you couldn't get Davis.js to work for you? Perhaps open an issue on the GitHub page.
If you want to use hash based routing with davis you need to include the hash routing extension. You then just need to include it in your page after davis.
The following setup should then allow you to handle routes
Davis.extend(Davis.hash)
Davis(function () {
this.get('/:page', function (req) {
FluidNav.goTo(req.params.page);
})
})
Assuming you have links in your page with the following
Page1
Page2
Davis will take care of handling the back button for you, so that if you click on the link for Page1 and then Page2, clicking on the back button will navigate to Page1 again.
If you have any problems please open an issue on the GitHub page detailing what you have and what isn't working and I can take a look at it.
The back button does not magically work. You need to code and listen for the event change!
In history.js, it shows you right on the front page:
// Bind to StateChange Event
History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
var State = History.getState(); // Note: We are using History.getState() instead of event.state
History.log(State.data, State.title, State.url);
});

Effectively handling Browser history and Back button [duplicate]

I want to change the way that content is displayed on my website:
var FNav = {
init: function() {
$("a[href*=#]").click(function(e) {
e.preventDefault();
if($(this).attr("href").split("#")[1]) {
FluidNav.goTo($(this).attr("href").split("#")[1]);
}
});
this.goTo("home");
},
goTo: function(page) {
var next_page = $("#"+page);
var nav_item = $('nav ul li a[href=#'+page+']');
$(".page").fadeOut(500);
next_page.fadeIn(500);
How do I change this JavaScript, so I can have a proper back button functionality?
What I have tried (Unsuccessfuly). These are the solutions that I tried but without changing the javascript above. That is why I think none of them seem to work.
Using the History.js method described here:
https://github.com/browserstate/history.js/ I fill out all the steps and
enter the scripts to the header, however only the URL in the URL bar
changes when I click on a link. When I click the Back button, the URl
changes accordingly, but content doesn't load. When I enter a URL in
the URL bar, I get sent to the home page.
Ajaxify and Gist method
described here: https://github.com/browserstate/ajaxify Achieves the
same as above, same issues as well
Davis.js method described here:
https://github.com/olivernn/davis.js Achieves nothing upon completion
of the installation instructions. No change.
jQuery BBQ Plugin method
described here: http://benalman.com/projects/jquery-bbq-plugin/
Achieves nothing, no change upon loading the .js file in the header
of the website.
I read this article and understood it:
http://diveintohtml5.info/history.html
I'm not sure why you couldn't get Davis.js to work for you? Perhaps open an issue on the GitHub page.
If you want to use hash based routing with davis you need to include the hash routing extension. You then just need to include it in your page after davis.
The following setup should then allow you to handle routes
Davis.extend(Davis.hash)
Davis(function () {
this.get('/:page', function (req) {
FluidNav.goTo(req.params.page);
})
})
Assuming you have links in your page with the following
Page1
Page2
Davis will take care of handling the back button for you, so that if you click on the link for Page1 and then Page2, clicking on the back button will navigate to Page1 again.
If you have any problems please open an issue on the GitHub page detailing what you have and what isn't working and I can take a look at it.
The back button does not magically work. You need to code and listen for the event change!
In history.js, it shows you right on the front page:
// Bind to StateChange Event
History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
var State = History.getState(); // Note: We are using History.getState() instead of event.state
History.log(State.data, State.title, State.url);
});

Prevent an exception with jQuery UI Tabs

I am adding some custom tabs to a jquery ui tab control.
$("#tabs").tabs("add","#tabContent0","CLICK ME TO CHANGE PAGE",0);
$('a[href="#tabContent0"]').attr("href","javascript:window.location='http://www.google.co.uk';");
Yes this is a bit of a hack, but it is exactly what i need and provide a nice way to give links back to previous parent pages.
jquery throws the following exception: "jQuery UI Tabs: Mismatching fragment identifier."
This is thrown on the line which appears to attempt to make the tab container visible in jquery ui (exact line wont help as is minified and custom build from official site).
Obviously im just redirecting but jquery has additional code to select the tab (which doesnt exist). In internet explorer, if the user has script errors enabled they will see the exception be thrown just before the window location changes, which I just cant have happen.
I cant put try catch around this code because it is the code inside jquery ui that throws the exception.
Is there anyway I can prevent this exception being thrown or achive the same thing but a different way without having to modified jquery ui ?
Edit: I am now wondering if there is a way to override the on click event hook placed on the element by jquery .. its definitely doing something there i cant see.
Edit: I have to log off now but I have made some progress, if someone can just help me get the right URL, using this code it prevents the exception, but redirects me to "http://myurl/undefined"
$('#tabs').bind('tabsselect', function(event, ui) {
if(ui.index<2) //ignore this will change to get current tab count -1 (so the end tab is left as it is
{
window.location=$('#'+ui.tab).attr("href"); //attr href is undefined, how do i use ui.tab properly to get the right url
return false;
}
});
It works OK for me in Chrome and IE8.
I also tried this code and it worked:
$("#tabs").tabs("add","#tabContent0","CLICK ME TO CHANGE PAGE",0);
$('a[href="#tabContent0"]').click(function() {
document.location='http://www.google.co.uk/';
});
Instead of changing href attribute, I add a handler on the click event of the new tab. This will make the tab to be switched and then the location changed.
From the jQuery UI docs:
$('#example').tabs({
select: function(event, ui) {
var url = $.data(ui.tab, 'load.tabs');
if( url ) {
location.href = url;
return false;
}
return true;
}
});
Though, jQuery's tabs, uh, method, ought to support passing in a selector for the tabs and panels so you could just make things links, instead of having to kick against the pricks.

Categories

Resources