NodeJS + JS: generating dynamic links, depending on current user selection - javascript

I'm trying to create a simple sorting option for posts in my blog. The problem is the last thing I want to use is a JS-based redirections because of the fact some users don't have JS enabled in their browsers, thats why they wont be able to sort posts in me blog. Let me give you an example:
I have several categories in my blog:
//categories selection
<ul>
<li class="active"><a id="cat1" href="/?category=music">Music</a></li>
<li><a id="cat2" href="/?category=photo">Photo</a></li>
<li><a id="cat3" href="/?category=cinema">Cinema</a></li>
<li><a id="cat4" href="/?category=computers">Computes</a></li>
</ul>
Also, I have two sorting options:
//sorting options
<div>
<a class="active">Last posts</a>
<a>Last comments</a>
</div>
Depening on current active elements, user is redirected on page with such parameters, e.g. '/?category=music&sort=posted' or '/?category=personal&sort=commented'.
For example, lets take that in categories selection 'CINEMA' tab is active at this moment (
<li class="actvie"><a id="cat3" href="/?category=cinema">Cinema</a></li>
). So, if user clicks Last comments link, it should redirect to
'/?category=cinema&sort=comments'
Another example: currently Last comments is active (
<a class="active">Last comments</a>
). User clicks on Computes in category selection and it should redirect to
'/?category=computers&sort=comments'.
So, are there any variants for performing such feature without JS? If no, could you suggest me the most elegant solution except manually running over every element in category and sorting optiona and generation link with JS/jQuery?
Thanks in advance!
SERVER SIDE:
db.collection("posts", function (err, collection) {
//getting posts dependinc on requested category
collection.find({category: req.query['category']}, {sort: [['time_added', -1]], limit:20}, function (err, posts) {
//getting posts and rendering page
});
});
UPDATE: I've found a so-so solution. For a separate category I render two div's with different posts list. One for 'Last posted', the second - for 'Last commented'. And the sort selector will just hide one div and shows another. The problem is just twice data size transfering to client side. I know, it will require a bit JS, but the main category links would be clear without '#'-hrefs. And sort options - it's just a toogle, it may not have real link.

Seems like you are doing a page refresh for selecting a new category. Use the selected category parameter to determine the URL of the sorting options. Would need some more code from your server side to give you a more concrete example.
If you don't want to use Javascript you will have to generate the href-attribute of your sorting links <a class="active">Last posts</a> dynamically based on which category is selected. How are you rendering the page today? Just static files? Have a look at a template engine like mustache.js and then you could do it like this:
<a class="active" href="/?category={{category}}&sort=comments">Last posts</a>
Have a look at this tutorial for an Node.js example using mustache.js
http://mrjaba.posterous.com/a-gentle-introduction-to-nodejs
Edited after your comment: Or something like this using EJS
<div>
Last posts
Last comments
</div>

Are you talking about doing the actual sorting on the client side or the server side? If the latter, there's no problem; just stick with the URLs you have and have the server rewrite them and redirect to the new ones (if you even have to do that; you could just treat the "shorter" URLs as the actual ones for the sorted content). This is no way relies on client-side scripting being available.
You can, of course, implement client-side sorting on top of this as a convenience for users who do have client-side scripting available; the key here is to use unobtrusive JavaScript (e.g. install handlers at load time to intercept clicks on the sorting links).

Related

Display a dynamically content growing page

Assume, I have a user page where user can select a subject to learn and a button to upload questions as well.
Basic View Of a Subject Page - User selects a subject and got a view like in the fiddle
<div class="dataContainer">
<div class="clsContextContainer">
Chapter1
Chapter2
Chapter3
Chapter4
Chapter5
</div>
<div class="clsContentContainer">
<div class="q"> Q: Question goes here
<div class="c">C: a) choice1 b) choice2</div>
<div class="a">AnswerButton</div></div>
<div class="q"> Q: Question goes here
<div class="c">C: a) choice1 b) choice2</div>
<div class="a"> AnswerButton</div>
</div>
</div>
</div>
I have shown a simple page of what I want. My doubt is how to design this page so additional question will be automatically added.
Solution1
User uploads single question or a file which contains list of questions. One of the administrator approves it[Not a duplicate question, valid one], Then it should be added to this subject page.
I can use handlebars.js and where I can maintain a template like I shown in the fiddle and a context page. Once one of the administrator approves, I can add new question(s) to the list of available contexts.[MODIFYING A FILE IN THE SERVER] So when user renders the page next time, new question will also be added.
My Doubt - Is it safe to modify a file in the serer through script?
Solution2:
I can maintain a table in the server questionsSubName. User adds new question(s).Admin approves it. So add that question to the table in the server.
While rendering, read questions from the db, then render it.
My doubt: I don't feel its a feasible one, since querying db often is not the best way for this kinda situation.
Solution3
I can have lists of files as shown in the fiddle [anchor tag]. User adds a new question. Admin approves it.
(i)Manually creates/modifies the files which corresponds to chapters. create - I want to limit 50questions per chapter. If one chapter reaches 50 questions, I need to create another. So create comes into the picture here. If a chapter has less than 50 questions, modify it.
ii) Do it through script.
But I am not sure whether I am doing it in the right way. Please suggest me what way I can do or Is there any other framework which can help me in this situation.
EDIT
After reading comments, handlebars js with tables is the best solution.
<div class="q"> {{{Question}}}
<div class="c">{{{Choices}}}
<div class="a">AnswerButton</div>
This could be my template page.
Context page will be like
{
Questions:[
{Q: questionString, C: ChoiceString},
next one
]
}
I have to read set of questions from the server, for eg: I have 5 chapters for a subject and 220 questions in the table.
Table format:
Question Id Column
Question Column
Choice Column
Answer Column
So If user clicks chapter1, I will read first 50 questions from the table and make a context, then render it. If user clicks chapter5, read last 50 questions and rmake a context, then render it.
Is it feasible?

Paging in a select tag without the next and prev page types

I'm trying to create a select tag paging with the following code:
<select ng-change="params.page(page)" ng-model="page" ng-options="page.number as page.number for page in pages"></select>
But the result is this:
Further debugging by using the following code:
<select ng-change="params.page(page)" ng-model="page" ng-options="page.number as page.number group by page.type for page in pages"></select>
brings me to the conclusion that the previous and the next pages (located at pages.type) are also included in the pages array.
So my question is, how do can I fix this? Is there a way to create an alternative array of only the pages that are really only pages or a way to filter the pages array based on the given types?
I managed to filter the "prev" and "next" page objects out of the pages array by defining a filter. I did this by adding | myFilter to the queryand adding a filter to my app.

How to stop clients from changing webpage data with inspector?

Ok, this is a problem I have been dealing with for some time.
My page loads with some li elements. All of them have their own id, which is their primary_key id in the database. Each element can be removed from the database. The process of removing is done by jQuery's $.POST method, getting the id of that element and passing it to a PHP file which gets the id and removes the corresponding record from the database.
In Google or Firefox's inspector, if I change the id value of an element, then press the remove button of that element, a different element with that id is removed.
Example: We want to remove "Mohsen" with id 45 from database.
<script>
$('li').click(function(){
var id = $(this).attr(id);
$.post('delete.php',
{r_id: id}
);
});
</script>
HTML:
<li id="45">mohsen</li>
<li id="35">vahid</li>
<li id="25">neda</li>
The code above is as originally loaded. When i click on "mohsen", "mohsen" gets removed from the database, since he has the id of 45. But, if I use the inspector and change the id values to:
<li id="25">mohsen</li>
<li id="35">vahid</li>
<li id="45">neda</li>
Now, when "mohsen" is clicked, "neda" which had primary_key id value of 25 in the database is deleted instead, which we did not mean to allow.
Is there any way to stop a user from manipulating the markup data with an inspector? In another words, how do I remove "Mohsen" from the database properly, even if its id value is tampered with?
Note: mohsen was an example, and each of li can be removed.
One way to reduce manipulation attempts would be not to delete by ID, but some unique random hash. You can either take that random hash as your primary key, or you create an extra column in your database.
data_tbl(id (pk), hash, value)
If your hash looks like: a89x1uAp3 for example, it'll be very very hard to figure out the hashes for other records based on that hash.
Just don't pass your ID via post, but your hash and the problem is restrained pretty much.
You cannot prevent the users to use inspectors to see the page, the only thing you can do is to implement your own server side validation if you wish to prevent deleting of some records.
Also, if possible, try to not expose your primary keys, only some derived information, like an hash as #Thomas David Plat suggests.
You cannot Prevent user from viewing/ changing data from inspector. The only thing you can do is to make server side validation e.g from client side send text which in your case can be "Neda","Mohsen" etc and 1st validate if that specific ID belong to that text/name. But this is purely server side thing, but AFA client side is concerned you cannot do it.

Boostrap tab urls on detail screens with Backbone

My BackboneJS app has a detail view, say for a Book, that is represented by url like editorial/book/edit/4. The Book view consists of several tabs, based on TwitterBoostrap markup, e.g. tabs General/Special/Admin for a Book.
If I use Boostrap tabs as prescribed in their docs, e.g.
<li><a data-toggle="tab" href="#special">Special</a></li>
then once tab is clicked URL in the address bar becomes invalid, instead of siteurl/editorial/book/edit/4#special it the nav bar displays siteurl#special.
Q1: What's the best way to build a tab with valid url with Backbone/Boostrap? The next step I aim at is to make this view reloadable, e.g. so that when a tab is selected and user hits "Reload" in browser, at least same view is loaded, ideally - with latest tab selected.
Q2: What's the ideal way - to build one router function for all detail screen with its tabs or split into a few router functions per each tab?
My recommendation would be to handle the navigation via JS side.
Answer to question 1
When a user clicks on the tab, on the handler use the backbone navigate function:
app.navigate("siteurl/editorial/book/edit/4" + '#' + tabId, {trigger: true});
(This examaple has the URL path hardcoded, just grab it with document.URL or another function that fulfill your needs)
Answer to question 2
That would depend on the logic you need to implement and if that logic is heavy or not. As in your question you said that each tab has a different view, I would suggest to just split the logic inside one router function as all of they apply to the same path (e.g. siteurl/editorial/book/edit/4) and they just differ in the fragment URL.
routes: {
"siteurl/editorial/book/edit/4#:tabId": "tab",
}
router.on("siteurl/editorial/book/edit/4#:tabId", function(tabId) {
//Split your logic based on the tabId
});

List view in HTML/JavaScript

Is there any easy way to create a a listview in HTML and set an onClick() listener for it like it can be done in Android? My requirement is that I want to retrieve data from the server and display it in a listview to the user. The data will be retrieved like - 10 rows at a time.
Then if the user clicks on more, next 10 rows will be retrieved. Then if the user clicks on a particular list item, show the details in another page.
A list in HTML looks like this.
<ul>
<li><a href="details/url/id">Title</li>
<li><a href="details/url/id">Title</li>
</ul>
The urls can goto the details page.
To add a more button you would use javascript and ajax to get more rows from the server, and append more items to the list when you get the response.
It's just a fast solution which uses Mootools, I consider your input is JSON which contain items in list array:
new Request.JSON(
{
url: '/list.json',
onSuccess: function(json)
{
json.list.each(function(key, val)
{
new Element('LI')
.set('text', val)
.addEvent('click', function()
{
alert('item '+key+' pressed');
// alert('item '+val.id+' pressed');
// considering val is an object instead of raw string, this way you must change set to something like this set('text', val.text)
})
.inject($('list'));
// any other thing you want add to your list item
});
}
}).get();
<ul id="list"></ul>
Key is the position of item in array, you can use an id instead which I added in a comment.
Rather than paginating the table, I prefer to use virtual scrolling like in SlickGrid.
SlickGrid has many modes of operation, but its core functionality is to only render the HTML of the rows you're currently looking at. As you scroll, the rows are dynamically created and destroyed as necessary. This allows you to display a grid with millions of rows.
The API allows you to load data on-demand, so rows will be fetched from the server (in groups of n) only as you scroll the grid.
You can try Jquery Data Tables:
http://datatables.net/
I suggest Ember.js. Ember.js has a powerful system of bindings and templates which are used to automagically synchronise Javascript objects with eachother and the DOM. It's overkill for what you're doing, but it's worth it if you're going to be doing anything complex with that list.
The Docs for Ember.CollectionView are here:
http://emberjs.com/api/classes/Ember.CollectionView.html

Categories