Parse URL and load corresponding data - javascript

I’ve successfully implemented routing and hashing with crossroadsJS and hasherJS on a SPA I’m working on. The data I’m loading from a REST API is entirely event based. This works fine for navigating through the website with click based events. However, I want to implement the ability to type in a URL (or refresh the current view) and load the data corresponding to that URL. I wrote a method like this:
// app.js
app.helpers = {
routeMagic: function (prop, clicked, type, el) {
var parser = document.createElement('a'); // setup parsing
parser.href = hasher.getURL(); // use hasher's .getURL() to find current URL
var splitURL = parser.hash.split('/')[2]; // split at second / ... example: /conditions/annual-wellness-exam => annual-wellness-exam
propArr = []; // set up array to store name property
for (var i=0, len=prop.length; i<len; i++) {
propArr.push(prop[i].name.replace(/,/g, "").replace(/\//g, "").replace(/[()]/g, "").replace(/\s+/g, "-").toLowerCase());
}
$(el).each(function () { // target li ... example ‘.returned-list li’
var val = $(this);
val.id = propArr; // append name to li id
var id = $(this).attr('id');
// this is only executing on click event, need it to execute on refresh or typing in URL
if (splitURL === id) { // find a match
console.log('match found');
clicked = val.children().attr('data-id'); // determine where to route the page to based off data-id
return false;
}
});
type(clicked); // init crossroads routing
}
};
Which would be called like so:
// routes.js
conResultsRoute = crossroads.addRoute('conditions/{name}', function () {
app.helpers.routeMagic(cache.lists.conditions, cache.justClickedCondition, api.endpoints.condition, '.returned-list li');
});
For this example, when I click on a ‘conditions’ link from a list of conditions, the expected results are returned on the following route. However, if I try to type in the same URL, I get a list back of all the data stored in the CMS rather than my filtered list like when I click through the app. I think the problem stems from not being able to target my $(el).each() on page load since it’s held in a different template, or possibly I have to reload my API calls every time I type in a URL. I imagine this isn’t enough data for someone to troubleshoot, so feel free to ask me more questions or check out a live (in development) version here
If you’re visiting the website, try a flow like this:
Conditions (main nav) -> Annual Wellness Exam -> Refresh or hit enter in URL bar

Related

Getting the value of # from a url

I have a problem. i have a website am working on. I have created a php script to fetch all the receipts id from the data base using pagination, and all works fine. But the problem is every receipt id, i have added a link so as when clicked a specified results will be displayed without loading the page.
The links are like :
G145252 G785965 and when each link is clicked will show http://test.com/?go=any#G145252
When clicked the page will not reload.
So what i need help with is how can i get G145252 from the url after when the link is clicked using javascript and print it using html?
i need to pass the value to the process.php as a $GET value so the i can load the receipt detail of the clicked id with out reloading the page.
Please note: there are a lot of get values before the #value i need to get out of the url address.
You should not be using the fragment identifier section of the URI for server side related tasks. This section is intended for client-side manipulation only. More info here.
You can use some other means such as query parameters to access this data.
For example, turn this:
http://test.com/enter code here?go=any#G145252
Into this:
http://test.com?go=any&hash=G145252
Then:
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
console.log(getQueryVariable("go")); // any
console.log(getQueryVariable("hash")); // G145252
NOTE: I know this is not the exact answer to your actual problem, but the question itself is presenting a bad practice scenario, thus my suggestion.
Credits for the getQueryVariable function goes to CSS Tricks: https://css-tricks.com/snippets/javascript/get-url-variables/?test=3&test2=5
Let's assume you're using jQuery.
Change all your links so that they have a common class name, lets say 'hashClick' e.g
My Link
To get the hash part when clicked, add a click event handler for those links
$('.hashClick').click( function(event) {
event.preventDefault();
var url = $(this).attr('href');
var hash = url.substring(url.indexOf('#')+1);
alert("You clicked " + hash);
// or at this point you can do an AJAX call
// or GET request to process.php with hash as one of the parameters
})
suppose this is the link
http://test.com/?go=any#G145252
to get the hash value
window.location.hash
which will return you #G145252
and
window.location.hash.substring(1) will return you "G145252"

GridMvc get id attributes from other pages in a paged Grid

I am using GridMvc to show data from database. GridMvc provide filter and sorting grid which is very useful. But now I meet a problem: I want to use JQuery to get a list of id attributes and pass this list to backend. But the Grid is Paged with 30 records per page. So I can only get a list of 30 ids from Page 1. Here is the paged grid:
What I want to do is get all href values(e.g. get a list of XX from page div). And when user trigger Export button, I define an JS Export function:
$('#Export').click(function () {
//Todo: Select all data from front end. Send a list to backend.
var Items = new Array();
var hrefs = new Array();
$('.pagination li').each(function () {
hrefs.push($(this).find('a').attr('href'));
});
var i = 0;
//var items = DeleteItems();
while (i < hrefs.length) {
//redirected to different pages
document.location.href = '/GridView' + hrefs[i];
//Save data
$('#PCA-grid table').find('.grid-row').each(function (index, item) {
//Find target items
var id;
var $checkbox = $(this).find('.DeleteSelected:first');
//Set a for loop here to
if (!$checkbox.is(':checked')) {
id = Number($checkbox.attr('id'));
if (id != NaN) {
Items.push(id);
}
}
});
i++;
}
//Sent list of ids to backend. Using URL redirect
window.location.replace('/GridView/Export?items=' + Items);
});
The basic thought has been described in code above. What I want to do is get urls from page tag. In while loop, try to redirect to target page and then push id attributes in this page to Items Array. But when I debut using Chrome tool, the while loop is not working as expected. There is no redirection happens.
Am I wrong with this problem? I just want to get id attributes from all pages in current grid and then pass this Items Array to backend. So anyone help me?
As far as I considered, it's hard to get all id attributes that needed to be downloaded with paging in grid. What I did was redirecting page to another view. In that view, I hidden same grid with no paging. And sent ids needed to be downloaded from grid to backend, then generated file for client user.
Not sure whether this way is best practice. But I used this method solved this problem.

Checking if a URL contains a value with javascript

I am working on a feature for my site that allows the user to use the back button and not have to load more database results.
I start by loading 16 results, and then there is a load more button which loads the next 16. In the ajax success i change the href of this button so the url changes to e.g. domain.com/#1 to #2.
I wrote this last night:
// First get the page URL and split it via # signs
var parts = location.href.split('#');
// now we run a check on the URL and see how many 'parts' there are
if(parts.length > 1)
{
var params = parts[0].split('?');
var mark = '?';
if(params.length > 1)
{
mark = '&';
}
location.href = parts[0] + mark + 'page=' + parts[1];
}
Which gets the URL, and redirects the user the same page but converts the fragment number to a page number. From this i then use a PHP $_GET and set the limit claus last value from that.
This works fine. But its primitive. Let for instance say i push back and the URL becomes:
www.domain.com/?page=1
If i then click to load some more data, the page url becomes:
www.domain.com/?page=1#2
If the user then visits another page and comes back then they get directed to:
www.domain.com/?page=1&page=1
Whats the best way around this? I was thinking of running a check on the URL at the same time as looking for a fragment and if the URL has a page variable i then add that variable to the fragment variable and the page URL becomes ?page=THE SUM NUMBER
Any help on modifying the snippet i posted above to check the URL for a page value and then add the two together before the redirection?
Thanks!
You need to use location.search to get the query string on a URL:
var queryParameters = location.search.split('&');
Then you can loop through the queryParameters and check if page is set:
var pageNumber = 0;
for(var i = 0; i < queryParameters.length; i++)
{
var keyvaluePair = queryParameters[i].split('=');
if(keyvaluePair[0] == 'page')
{
pageNumber = keyvaluePair[1];
break;
}
}
Please see the documentation on the MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Window.location
You might also find this example useful for returning one value:
https://developer.mozilla.org/en-US/docs/Web/API/Window.location#Example_.236.3A_Get_the_value_of_a_single_window.location.search_key.3A
If you want to get the information after the #, you need to use location.hash. The MDN documentation I linked also has information on location.hash.

Reload div with same content

I've a div which contains a list of clients pulled from Mysql.
On the same page I have a jquery dialog box which pops up to allow a user to add a new client.
What I want to happen is that when the user adds a new client the containing the list reloads so the new client is available.
Is there a way to simply reload the div without using the Load() function as this is causing errors when I redeclare my classes that populate the list ?
Of course. Without looking at your code, your confusion here suggests that you don't understand "Separation of Concerns". Separate the process of getting information from the process of displaying that information. When the user enters new information, add that to javascript array or object of information you got from the server and also send that off to the server to be updated in the database. Then run the display function again using the updated information to include the new information. Ideally, the display process will use existing markup if it can, rather than deleting it all and recreating it all just to add one item. Here's a very basic example (click here). Ideally, you would take this concept and expand on it to make it optimally efficient and organized.
Here's the sample code from my jsbin. Please keep in mind this is just to get you started.
var info = [1,2,3,4,5]; //this is what you got from your ajax call to the server
function render(element, info) {
//this is a lazy system that recreates/replaces all the markup each time. I suggest doing this more efficiently, but that is work for you to do :)
var frag = document.createDocumentFragment();
var len = info.length;
for (var i=0; i<len; ++i) {
var p = document.createElement('p');
p.textContent = info[i];
frag.appendChild(p);
}
element.innerHTML = '';
element.appendChild(frag);
}
var targetElem = document.getElementById('targetElem');
render(targetElem, info);
var addButton = document.getElementById('add');
var input = document.getElementById('infoInput');
addButton.addEventListener('click', function() {
info.push(input.value); //update the information
render(targetElem, info); //render the updated information
});
Either of these should give you success.
success: function(userinfos) {
$("#users").append($('<tr><td>'+userinfos+'</td></tr>'))
display_message("user added");
}
$.ajax({
type: "GET",
url: "ht.tp://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData +"&relationship="+ forData +"#",
success: function (response) {
$("#testDIV").html(response);
}
});

Display user profile in div using ajax

I want to display user profile when admin mouser over on username link. If this is first time, user profile is displayed; then next time ajax should not fire and display user profile without ajax fire.
To implement the functionality proceed step by step:
On mouseover of the username, implement an ajax call that renders user profile in html near the username
Through javascript, implement functionality such that when user leaves the username/userprofile, the user profile div is now hidden
While making ajax calls in #1 above, check if the div already exist which contains user profile for the userid which you are trying to request. This can be easily achieved by having some id in the user profile part and checking if that #user_profile_#{id} div exists.
Your requirement is too broad to be able to provide any code...
If you have problem in implementation of any of the above parts, post them as question separately one by one..
You need to know the id and the class of the username link.
You can make jQuery listen to the hover, when that event occurs you can call the function which will do the ajax.
But, you need to know the id of the user, the best way to do that is to do something like
<a href='user123.php' class='userHref' id='user_123'>I want to be hovered</a>
Now you have a link to hover over.
$('.userHref').live("hover", function()
{
var userHrefId = $(this).attr('id');
var userHrefIdSplit = userHrefId .split('_');
var userId = userHrefIdSplit[1];
useAjax(userId);
});
Now you have listened to the hover by listening to any hovering over a link of the class userHref, jquery has responded by taking the id of the a element, splitting the id into 2 seperate items, where the second one indicates the user Id.
Now we have also called with useAjax function and we have sent the id of the user. Now you can POST the userId to a known backend site (rails in your example), which will query the database and return the url to the user image. We then only have to know the id of the div element which you want the image to appear in.
function useAjax(userId);
{
var id = userId;
var select = true;
var url = '../scripts/ajax.php';
$.ajax(
{
// Post select to url.
type : 'post',
url : url,
dataType : 'json', // expected returned data format.
data :
{
'select' : select, // the variable you're posting.
'userId' : id
},
success : function(data)
{
// This happens AFTER the backend has returned an JSON array
var userUrl, userImg, message;
for(var i = 0; i < data.length; i++)
{
// Parse through the JSON array which was returned.
// A proper error handling should be added here (check if
// everything went successful or not)
userUrl = data[i].userUrl;
message = data[i].message;
userImg = "<img src='"+userUrl+"' alt='' title='' />";
$('#someDiv').html(userImg); // Here's your image.
}
},
complete : function(data)
{
// do something, not critical.
}
});
}
I'm not familar with rails but you can probably program the backend in a similar wasy as I exmplained here: Javascript function as php?
Search for my answer, it should give you a very detailed example.
I hope this helps.
Tip for the future: Try and google first :)
Assuming you're using jQuery, bind a hover event to the user name link. As so:
$('.username').hover(function (e) {
console.log("i'm hovering!! on id: "+$(this).attr('data-user-id')); //See the next step for where this came from
}
Next, add the user's id to the username element, perhaps in a data attribute:
<span class="username" data-user-id="1234567890">Username</span>
Next, keep a record of which users are already loaded, perhaps by id. When you fetch something new, add it to the object. I like to keep objects like this on the window.
window.loadedUserInfo = {};
On hover check if the userId key exists in this object. If it does, user it. If not, use an ajax call to get it:
$.ajax({
url : "path/to/userinfo"+userid, //I'm assuming you're using restful endpoints
type : "GET",
success : function (res) {
window.loadedUserInfo[userid] = res;
//Format your popover with the info
},
error: function (jqxhr) {
//something went wrong
}
})
As for the popover itself, you could probably use a bootstrap popover.
Putting it all together:
$(".username").hover(function (e) {
console.log("i'm hovering!! on id: "+$(this).attr("data-user-id")); //See the next step for where this came from
if (typeof window.loadUserInfo[$(this).attr("data-user-id")] == 'undefined') {
$.ajax({
url : "path/to/userinfo"+userid, //I'm assuming you're using restful endpoints
type : "GET",
success : function (res) {
window.loadedUserInfo[userid] = res;
//Format your popover with the info
},
error: function (jqxhr) {
//something went wrong
}
})
} else {
//populate popover with info in window.loadUserInfo[$(this).attr('data-user-id')]
}
}

Categories