So I'm following this tutorial:
http://www.tinywall.info/2012/02/change-browser-url-without-page-reload-refresh-with-ajax-request-using-javascript-html5-history-api-php-jquery-like-facebook-github-navigation-menu.html
My goal is to load the actual content of my views and change the browsers URL without reloading the page. However, because I'm using CodeIgniter as a framework of my application, I can't get it to work properly. I have a controller where I'm loading all of my Dashboard's views, ones I want display inside my div called content_container.
The problem is that every time I click another anchor tag to get different view to load through ajax request, it adds another "dashboard" -in my url and of course it doesn't display the view after that. So after couple clicks, the URL would look something like this: "dashboard/dashboard/dashboard/profile". I've tried to split the URL with Javascript, but that didn't help me.
One solution would be to create single controller for each view, but I consider it as a bad practice and the code is a lot more cleaner with just one controller to handle all the views.
Here's the controller:
<?php
class Dashboard extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->output->nocache();
$this->load->model('subject_model');
$this->load->model('user_model');
}
public function index()
{
$this->load->view('header');
$this->load->view('dashboard');
$this->load->view('footer');
}
public function users()
{
$data['users'] = $this->user_model->getUsers();
$this->load->view('staff_users', $data);
}
public function lomake()
{
$this->load->view('lomake');
}
public function profile()
{
$data['userinfo'] = $this->user_model->getUserInformationById($this->session->userdata('user_id'));
$this->load->view('myprofile', $data);
}
public function subjects()
{
$this->load->view('subjects');
}
}
?>
And here's my dashboard view (part of it):
<aside id="left_control_panel">
<ul id="left_control_links">
<li>
Home
</li>
<li>
Subjects
<span class="list_total_count"><?=$total_subjects?></span>
</li>
<li>
Query
</li>
<?php if($this->session->userdata('user_type') == 'admin'):?>
<span class="left_control_heading">User management</span>
<li>
Users
<span class="list_total_count"><?=$total_users?></span>
</li>
<li>
<a class="add_user" href="add_user">Add User</a>
</li>
<?php endif;?>
<span class="left_control_heading">Account management</span>
<li>
My Profile
</li>
<li>
Sign Out
</li>
</ul>
</aside> <!-- end of left_control_panel -->
<div id="wrapper_loggedin">
<div class="content_container">
<! -- I will display all the data from different views in here -->
</div>
</div> <!-- end of wrapper_loggedin -->
And finally the JS part which can also be found in the tutorial:
$(function(){
$("a[rel='tab']").click(function(e){
//e.preventDefault();
pageurl = $(this).attr('href');
$.ajax({url:pageurl+'?rel=tab',success: function(data){
$('.content_container').html(data);
}});
//to change the browser URL to 'pageurl'
if(pageurl!=window.location){
window.history.pushState({path:pageurl},'',pageurl);
}
return false;
});
});
/* the below code is to override back button to get the ajax content without reload*/
$(window).bind('popstate', function() {
$.ajax({url:location.pathname+'?rel=tab',success: function(data){
$('.content_container').html(data);
}});
});
Application/config/routes.php
$route['dashboard'] = 'dashboard/index';
$route['dashboard/(:any)'] = 'dashboard/$1';
well, with my specific situation I had thousands of products organized in categories and sub categories. Well..thats a ton of urls and controllers to write. so what i did was make a category template, a sub category template and a product page template. then made routes like below in my application/config/routes.php file:
$route['products'] = 'products/index';
//so i know now they are on a category page and $1 is the name of the category.
//i can go query my db and get all subcategorys and the products under each now.
$route['products/(:any)'] = 'products/category/$1';
//the 1 and 2 here are category and subcategory from the url. so i know from this to
//use these in my query to grab all products in this category and subcategory.
$route['products/(:any)/(:any)'] = 'products/subcategory/$1/$2';
//i know this is gonna be a product page. and i know the category, the sub category and the product name. in this case all i really need is the product name since there is only one product with that name.
$route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3';
in your situation you can do the same. use your urls, your taking the time to build them so use them. in javascript you can send them back to your controllers via 'window.location.pathname'; all you have to do is split it up and you can use the same mentality to load a page and know exactly where you are at.
Also, in your ajax url property make sure your url is either an absolute url, or it references the root first. I think i know what your issue is. you are using a url like "users/dashboard" in your url property when it should be "/users/dashboard" you need to always go to the root and get the controller, otherwise it uses the url and will always take on the "users/dashboard" to the current url you are on. So if you are on "users/dashboard" and go load it again, your actually telling it to load "/users/dashboard/users/dashboard" and this becomes an infinite loop. Just put a backslash in front of your url and it will always reference the root.
I just did this very same thing. The way I did it was first make a dynamic route to always point to the same controller. $route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3'; etc. then anytime your page is loaded via a url (if someone puts in a specific url) you will still get content (bookmarks still work, you can send specific urls to people etc). Then what I did was every link that changed content also applied a data attribute to build the url out, i would also use those to pass back to the same controller. That controller also checks if the request is coming from an ajax request or not...if it is, you just load the page content...if it isnt then load the full template. its really not that hard and you actually almost have what i have. I think you are over thinking it. But the first thing i would do is make sure going to every page with the url works first. then try to get the ajax part working. The key is to detect if the request is coming from ajax or not within your controller. Then you can differentiate the two.
Also, I would strongly recommend you reading the user guide. The routes are usually one of the first thing you should cover when you start building projects with Codeigniter.
http://ellislab.com/codeigniter/user-guide/general/routing.html
Answering your question on the core controller. The answer is yes, you create a controller inside your core folder. It has to have a specific name. In your application/config/config.php file you should have:
$config['subclass_prefix'] = 'MY_';
This defines your prefix to any extended core controllers, models or system classes. Most Codeigniter system classes can be extended and you can overwrite properties (variables) and methods (functions). In your case you would drop a file called MY_Controller.php in your application/core folder. In this controller you would approach it like any other controller you write with the idea to not have to keep rewriting the same code over and over again, or to change the way the default Controller operates. You should read up on how a php class is suppose to work and the purpose of using them. Codeigniter doesn't really use them the way that you are suppose to use a class, but they approached it with the MVC approach. Usually, a class is referenced to as an object. Think of a class as a Bear. A bear has weight, age, length, color, height. All of these are called "properties". A bear can also eat, drink, and hunt. Each of these are called "methods". A more detailed version of a bear would be a polar bear, grisly bear or panda bear. These could be children of the bear object (they would extend the Bear object). Any child object inherits its parents properties and methods. But their values and actions could differ. The polar bear is a different color, size, height than the panda bear but it still eats, drinks, and hunts. Some properties and methods might not change, so there is no reason to rewrite those in the child classes. So in your case, the core controller can handle things that every page does. It can verify sessions, track a users activity, define global error messages etc. Ive even gone so far as to create a method in my core controller that loads my template pieces together (header, footer, sidebar, content) so i didn't have to keep stacking $this->load->view() when i was loading pieces of my template. All I had to do was pass the content and data that needed to be passed and it loaded my template everywhere. You also need to understand how the __construct works. You can think of the __construct as a function that always runs first before your page loads. so by defining a construct in your core controller you can then fill in data automatically. Browse these links as they go into a deeper explanation on how to use these features and shows examples.
http://ellislab.com/codeigniter/user-guide/general/core_classes.html
http://www.php.net/manual/en/language.oop5.php
Please give me a up vote if this guided you in the right direction :) Im trying to build up my points and profile and eventually link my account up to my website so it proves my plethora of php & codeigniter knowledge to any future employees.
Related
I am using Gatsby as a frontend to a WordPress backend. I have successfully fetched the menu items but I now need to link them to the pages I have created. I have added the Menu Links in my Gatsbyconfig.js but I have no idea on how I can go about mapping it to the menu items at the same time as the menu itself. It ends up contradicting each other. Is this possible to do? I am quite new at graphQL. Never touched it till this project. Below is the GraphQl Query
{
allWpMenuItem(filter: {menu: {node: {name: {eq: "Navigation Menu"}}}}) {
edges {
node {
label
}
}
}
site {
siteMetadata {
title
menuLinks {
name
link
}
}
}
}
The label holds the name for each menu and the link holds the link to the pages I have created. I am trying to fix this into this bit of code
<div>
{props.allWpMenuItem.edges.map(edge =>(
<a href="#" key={edge.node.label}>
{edge.node.label}
</a>
))}
</div>
I am trying to query the menu links change the anchor tag to the link item and then point it to the menu link.
The short answer is that you can't, natively each query is a separate entity. However, you can combine queries using createResolvers, for further details check: https://github.com/gatsbyjs/gatsby/discussions/28275 (thanks LekoArts for the feedback).
However, you have a few approaches to bypass this limitation. Given that each query is transformed into a standalone JavaScript object, you can always manipulate them using native JavaScript filtering or doing whatever you need. The idea is to create an empty object and populate it with links and labels, in a single loop or using two different, then, in your component, iterate through this object instead of through the props like you are doing now.
I can't create a minimal example without knowing the internal structure or without knowing what's inside menuLinks.name.
By the way, if you are using internal navigation I would hardly suggest using <Link> component, among other things, using the #reach/router (extended from React's router) will only render the necessary parts of each component, creating smoother navigation than using native anchor tag, what will refresh all the page.
I have a template which is nested inside another template which I want to load when i click on a button.
So the nested template is loaded dynamically. This is what I have done so far.
This is the main body.html (this loads when a url is provided in the browser e.g. http://url#/newtemplate)
<div ui-view> </div>
Other section of the code has been removed for brevity
This is the new_template.html which I expects it to show when I click a button.
When I put a template name directly like below i.e. when I hard code it
<div ui-view="number1"></div>
It loads the template fully.
This is the dynamic model
<button ng-model="template_name" ng-value="number1">Button1</button>
<div ui-view="{{template_name}}"></div>
{{template_name}}
The above does not load the template as I expected. but it shows the string number1 when
the button is clicked
What can I do for it to load the template....
This is my controller
.state('parent',{
url: '/newtemplate',
views:{
'':{
templateUrl: "parent.tpl",
contoller:"controller",
},
'number1#parent':{
templateUrl:"number1.tpl",
contoller:"formcontroller"
},
'number2#parent':{
templateUrl:"number2.tpl",
contoller:"formcontroller"
},
'number3#parent':{
templateUrl:"number3.tpl",
contoller:"formcontroller"
}
}
})
Strange enough when I used the dot notation it did not work so I have to use the absolute naming method.
I also noticed that when I added the nested views as shown above the time it takes before the template gets loaded take a very long time.
Please I would appreciate any help which can allow me to load a nested view at runtime (possibly very fast)
Expecting more answer
I still hope that the I can make use of ui-view/ui-router because of the ability to make use of controller.
I'm not sure you can use uiView to load html dynamically.
I would try another possible solutions:
Use directives
Using ngInclude
I'll leave you an example with ngInclude: https://next.plnkr.co/edit/M5hl71mXdAGth2TE?open=lib%2Fscript.js&deferRun=1&preview
This may seem like a dumb question. But I have no idea if it can be done. So before I start the process of making a portfolio site, I would like some pointers. Otherwise, I will just go with another design.
My question:
When using the ascencor.js plugin, everything on my site is in one file. I will therefor never go to a new url, like /contact or /about.
But then I wondered, what about google?
All of my content would be put inside different different classes, but in the same file:
<div class="floor floor-1">
<span class="text">Floor 1</span>
</div>
<div class="floor floor-2">
<span class="text">Floor 2</span>
</div>
Check the example here: http://rplambech.dk/ascencor/
So yeah, with this method, I will never change the url, so I can therefor only index one page.
Is there a way that I can change the URL without updating the site? And will I be able to go to http://rplambech.dk/ascencor/floor5 for example?
In case it's not possible, can I then at least overwrite the title of the page, each time I click to a new "page". With some PhP for example.
Or should I just go with a completely different approach? :)
From the context of your question, and its comments, you're looking for the term single-page-application.
There are many ways of doing this, some of them make use of the history object in order to support the browser's "back" and "forward" buttons.
I'd recommend you to do a search of the term "single page application" and in the meantime examine some (or all) of the following frameworks (they will ease your development and make your life easier instead of dealing with # and nasty low-level ajax calls:
backbone.js
angularJS
ember.js
It can be done using hash links, originally designed to jump to a certain div on the page are now often used to load dynamic pages on a single page
so you could link to http://rplambech.dk/ascencor/index.html#floor5 for example
and then have some javascript like
var loc = location.hash.split("#")[1];
then
if(loc == 'floor5'){
//execute goto floor 5 code
}
Using history.pushState with HTML5 as stated here.
<script type="text/javascript">
var stateObj = { foo: "bar" };
function change_my_url()
{
history.pushState(stateObj, "page 2", "bar.html");
}
var link = document.getElementById('click');
link.addEventListener('click', change_my_url, false);
</script>
URL:
<a href="#" id='click'>Click to change url to bar.html</a>
No you can't change the URL without going to the server.
JQuery does however have a cool page loader that will load a page.
How to put a whole html page in a div using jquery?
You cannot change the url "/ascencor" to "/ascensor/floor5" without refreshing the page.
But you can change to "/ascensor/#floor5" (added hash sign). I suggest you try out angularjs for more information.
I have single page app made with ember.js and I have some problems with implementing social sharing.
I need to implement into hbs template something like this:
Link
However when this is rendered into browser there are additional script tags concatenated within the href string, eventually the link works and I am redirected but instead title I get something like this:
<script id='metamorph-190-start' type='text/x-placeholder'></script>
MyTitle
<script id='metamorph-19...
Where I need just MyTitle.
More specifically I use the following hbs template for facebook sharing, the model is initialized into the router:
<a href="https://www.facebook.com/login.php?next=http%3A%2F%2Fwww.facebook.com%2Fsharer%2Fsharer.php%3Fs%3D100%26p%255Btitle%255D%3D{{model.title}}%26p%255Burl%255D%3D{{model.url}}%26p%255Bsummary%255D%3D{{model.summary}}%26p%255Bimages%255D%255B0%255D%3D%2540Model.EventImage%2527%253EShare&display=popup"
target="_blank">
<img src="http://www.simplesharebuttons.com/images/somacro/facebook_img.png" alt="Facebook" />
</a>
I also tried third party libraries, like janrain, ShareThis or AddThis, but with them I had initialization problems, buttons were not shown at all when placed into template, and also had problems with messages customization from the model.
Thanks,
Igor
Approach 1 - Using unbound
To get rid of the metamorph tags surrounding your model value, try using the unbound option which does exactly that:
Link
Approach 2 - Computing the URL
In the case you need the model property to be bound and reevaluating when the model changes, then a different approach might be better like for example generating the URL in the controller backing up your template.
Assuming your controller is e.g. ApplicationController and the links live in the correspondent application template then you could do the following:
App.ApplicationController = Ember.ObjectController.extend({
url: function() {
var url = this.get('model.url');
var title = this.get('model.title');
// grab here as many properties you need from your model
var href = 'http://someaddres.com?u=%#&title=%#'.fmt(url, title);
return href;
}.property('model')
});
And then use the computed url property like this in your template:
<a {{bind-attr href=url}} target="_blank">Link</a>
Hope it helps.
This actually doesn't work that well since this will open a new browser tab\window instead of the desired popup window you get when using the suggested js code form facebook # https://developers.facebook.com/docs/plugins/share-button/
Unfortunately, you also need to create an 'action' within a Ember.View (for example) that calls window.open(url,"blah","width=300,height=500")
I have seen this question before but I haven't found a working solution.
The question is quite easy.
If I call a page like this.
div.load('page?foo=bar');
I want to be able to retrieve foo in some way an use it in a javascript called by page. But I only manage to obtain the paramethers of the parents url.
I know I can declare variables in the parents javascript code but that is not my preffered way.
So I really hope someone has a solution to this problem.
♥ you guys
You could use something like this to parse the URI:
http://blog.stevenlevithan.com/archives/parseuri
Then you can access the parameters easily from the parent page:
// Set the link that we want to load/examine
var link = 'page?foo=bar';
// Load the link content (as per your code)
div.load(link);
// Grab whatever variables we want from the link
var uri = parseUri(link);
var foo = uri.queryKey.hasOwnProperty('foo') ? uri.queryKey.foo : false;
alert(foo);
EDIT:
As bfavaretto already commented, the content loaded in via AJAX is just a string. It's not a page that will be aware of its URI.
However, if you really want the loaded content to be able to access its URI, just make it available in the content itself. For example:
$('#my_div').load('page?foo=bar)
And in the content of "page?foo=bar":
<div class="container" data-page-uri="{{ insert uri here with php, ruby, whatever }}">
<!-- my page content -->
</div>
Now in your loaded content, you can determine the URI by finding the relevant div with the "data-page-uri" data attribute. Once you have the link, you said that you know how to grab the parameters from it...
Hope that helps.
I think you have two solutions. One, if page has a hidden div, with the data needed, the second one, probably the ajax response object has the caller url. You should study the response xhr object.