Clarification:
I really don't want to embed my js in my html. The suggestions I'm
getting, like, this or that post might contain the possible answer,
well in those answers, they embedded their js in html. Both my
js and html is large. So embedding will surely make them messy and
hard to debug
In my project there's a module where user can see details about product and add products to cart. For this he needs to specify the number of products he wants to add. It looks like
For this I have a + and - icon. I have a js file where it increments or decrements each time + or - has been clicked.
Now, what I want is this:
A user can add products but if the total number exceeds the number of
products stored in the database, he can't add products even if he
click the + button. For example, if there are 4 items and he clicked
5 times then on the 5th click the amount will remain 4, won't
increase.
So I need a django variable in my js file. I looked up how to do that, and I found some solutions.
Some solution says var data = '{{data|escapejs}}' this while some solution says
<script>
var myTable = {% autoescape off %}{{ table_data }}{% endautoescape %};
</script>
But I don't want to embed js on my html like this. Here is my js file:
function incrementValue()
{
var value = parseInt(document.getElementById('quantity').value, 10);
value = isNaN(value) ? 0 : value;
value++;
document.getElementById('quantity').value = value;
}
And my html, from where I am calling this js like this:
<span class="btn btn-default btn-lg btn-qty" onclick="incrementValue()">
<span class="glyphicon glyphicon-plus" aria-hidden="true">
</span>
</span>
<input class="btn btn-default btn-lg btn-qty" id="quantity" value="0" />
<span class="btn btn-default btn-lg btn-qty" onclick="decrementValue()">
<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
</span>
</span>
What is the best way to pass django variable to js or, How should I pass the django variable to my js so that there will be no vulnerability or no security issues and also I don't want to embed js in my html.
Related
I am developing on localhost: http://127.0.0.1:8000
When I perform some search on the website, I want that if the query does not return results, the New entry button allows the creation of a new article from what has been searched in the search input.
So if I search 'whatever' and there is no article called 'whatever', the button should redirect me to the creation page of the article 'whatever'.
<script>
$( document ).ready(function() {
var newEntryUrl = window.location.hostname+":8000/wiki/_create/?slug="+"{{ search_query }}";
document.getElementById('newEntrybtn').setAttribute('href',newEntryUrl);
});
</script>
{% for article in articles %}
{% block wiki_search_loop2 %}
{% endblock %}
{% empty%}
There is no page created for '{{ search_query }}', would you like to create a page nowee?
<a class="btn btn-success" id="newEntrybtn" role="button"><i class="fa fa-plus" aria-hidden="true"></i> New entry ({{ search_query }})</a>
{% endfor %}
To calculate the url to create the new article, I use this line:
var newEntryUrl = window.location.hostname+":8000/wiki/_create/?slug="+"{{ search_query }}";
If I do an alert(newEntryUrl); it returns the desired result: 127.0.0.1:8000/wiki/_create/?slug=whatever
However, if I click the newEntrybtn button, it redirects me to the following url: http://127.0.0.1:8000/wiki/_search/127.0.0.1:8000/wiki/_create/?slug=whatever
Which is strange to me since at no time have I assigned the href attribute to the button, much less have I assigned it any value. It seems that somehow, by default, it gets the value of the current page.
My question is, how can I remove the current page: http://127.0.0.1:8000/wiki/_search/ so that the button href just has this structure: 127.0.0.1:8000/wiki/_create/?slug=whatever ?
I think you are appending the value twice. Once when the page loads because it is in the document.ready function and once again when the button is clicked. Try writing it in another function and calling the function when the button is clicked.
setAttribute is being called twice
https://codepen.io/sijbc/pen/zYNdrmz
.setAttribute() is being called twice
function createUrl(){
var newEntryUrl = window.location.hostname+":8000/wiki/_create/?slug="+"{{ search_query }}";
var newEntryBtn = document.getElementById('newEntrybtn')
newEntryBtn.addEventListener("click" function(){
newEntryBtn.setAttribute('href',newEntryUrl);
})
The problem is because you are using a relative URL as the href, causing the browser to append this to the current URL you are looking at.
In your example, your button will be set as follows:
<a class="btn btn-success" id="newEntrybtn" role="button" href="127.0.0.1/...">
And clicking on it will append the href to the current URL since the browser will consider it as a resource of the current page.
Following your example, using an absolute URL will allow you to go directly to the URL as you have it set as long as you know the full structure (in your case, you are missing the protocol/scheme):
<a class="btn btn-success" id="newEntrybtn" role="button" href="http://127.0.0.1/...">
Or ideally you should use a relative URL by defining correctly the segment of the URL it represents (defining the path from your host where the resource is located):
<a class="btn btn-success" id="newEntrybtn" role="button" href="/wiki/_create/...">
(notice how the URL starts with a slash and omits the server host and protocol).
It is preferred in most cases to use relative URLs to make your code run regardless of the server (environment), meaning it will always use the same server or protocol of the current URL. But it's up to you based on your needs.
References:
https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_URL#absolute_urls_vs_relative_urls
I found a good solution without using JavaScript, in just one line of code:
<a class="btn btn-success" href="/wiki/_create/?slug={{ search_query }}" role="button"><i class="fa fa-plus" aria-hidden="true"></i> New entry ({{ search_query }})</a>
Thanks to those who have posted an answer, you have inspired me a lot.
When jsevent triggered , it forwards link parameter to data-url attribute of a button and when user click that button it redirects to django backend view but there is a problem with parsing line of JS
$('#btn_del').attr('data-url',{% url 'event_delete' + event.id + %});
is there any chance to combine that syntax ?
Thank you , have a nice days.
JS:
eventClick: function(event, jsEvent, view) {
$('#modalTitle').html(event.id);
$('#btn_del').attr('data-url',`{% url 'event_delete' ` + event.id + `%}`);
$('#calendarEditModal').modal();
console.log(event.id);
}
url.py
....
url(r'^event/(?P<pk>\d+)/delete/$', event_delete, name='event_delete'),
....
Html button that redirects to django
<button id="btn_del" type="button" class="btn btn-primary js-delete-events" data-url="">
<span class="glyphicon glyphicon-pencil"></span>
Edit
</button>
Result should be like this format event.pk is going to be our parameter numeric value , it's ok.
<button type="button" class="btn btn-primary js-delete-events" data-url="{% url 'event_delete' event.pk %}">
<span class="glyphicon glyphicon-plus"></span>
button
</button>
/event/1/update/ is the last result of seen from browser inspect. But I need to write inside jsEvent with django syntax to able to reach backend view which is {% url 'event_delete' event.pk %} something like that.
No, it cannot be done that way... Parsing of your templates (the {% url %} tag) is done on the server before even the browser receives anything. Browser doesn't know what template tags are you using.
On the other side, JavaScript is executed in the browser, so template language has also no knowledge about variables inside it.
Solution for that is to use a package like Django JS Reverse. The second one is to pass full URL to the JavaScript, just like it receives the ID of the item.
I was wondering. It's not possible to put Javascript inside blade #if right? Is blade #if some form of php but using php code will be discouraged in view right? What should I do? Here's the logic of what I'm trying to achieve. Basically, what alternative ways are there to achieve what I'm trying to do? I'm trying to show button when the three conditions are met.
#if(isToday($one_parking_info->booking_data->m_bkl_end_date) && isBeforeElevenPM() && notEndInT($one_parking_info->booking_data->m_plots_address_city))
<button type="button" class="btn btn-primary btn-sm" onClick="cancelBooking('{{ $one_parking_info->booking_data->m_bkl_gov_id }}')">取消</button>
#endif
Blade is a form of php, so all work is done on the server. So you cannot call javascript functions inside #if expression. Instead you can run the functions in the controller and return a value to say if you should include the button or not or you can have a javascript to show or hide the button if you don't care if the users can find and show the button if they want.
Something like in your controller return view('your view')->with(['showButton' => $shouldShow) and in your view #if($shouldShow) and the rest of your code
Your js must be in public or a child, and would be something like this:
#if(isToday($one_parking_info->booking_data->m_bkl_end_date) && isBeforeElevenPM() && notEndInT($one_parking_info->booking_data->m_plots_address_city))
#include('script.js')
<button type="button" class="btn btn-primary btn-sm" onClick="cancelBooking('{{ $one_parking_info->booking_data->m_bkl_gov_id }}')">取消</button>
#endif
Another option could be <script src="{{ asset('js/scripts.js') }}"></script> instead of #include directive
i guess:
#if(isToday($one_parking_info->booking_data->m_bkl_end_date) && isBeforeElevenPM() && notEndInT($one_parking_info->booking_data->m_plots_address_city))
#include('script.js')
<button type="button" class="btn btn-primary btn-sm" data-id="{{ $one_parking_info->booking_data->m_bkl_gov_id }}">取消</button>
#endif
<script>
$('body').on('click','.btn-sm',function(){
var id = $(this).attr('data-id');
//
logic of cancelBooking
//
})
</script>
I have a view that gets data from Model and displays the information. I am getting a list of school with school name and school Id from Model and then using foreach loop, I am creating a dynamic table based the number of schools the Model returns.
Below is the code I have for my view.
#if (Model.SelectedSchool != null)
{
foreach (var sch in Model.SelectedSchool )
{
<table class="table-bordered">
<tr>
<td class="col-sm-9">
#sch.SchoolName
</td>
<td class="col-sm-3">
<button class="btn btn-default" id="recentlySelected" name="btnRecentlySelected" type="button">
Select
</button>
</td>
</tr>
</table>
}
}
Here SchoolName is the property in the list I am getting from Model.
SchoolId is also in the list.
Below is the view I get
Now, I want that when a user clicks Select button, beside each school name, that specific SchoolId, is passed to the .js file where I am handing the javascript functions and based on the schoolId, the javascript function, generates the address of the school.
My question is how can I link the SchoolId's that I am getting in the SelectedSchool list to the respective Select buttons.
Thanks in advance!
First of all, you are setting the same id to all the buttons generated from the loop. This is invalid HTML ! Id values should be unique. So delete the Id property (unless you absolutely need it for something. in that case you need to make it unique)!
You can keep the school id in html 5 data attribute and read it later in javascript as needed.
Assuming you have a property called SchoolId,
<button class="btn btn-default" data-schoolid="#sch.SchoolId"
name="btnRecentlySelected" type="button">
Select
</button>
You can have the same attribute value for name property. You can use this as your jQuery selector when registering the click event on these buttons.
Now some unobutrusive javascript to bind a click event on this button
$(function(){
$("[name='btnRecentlySelected']").click(function(e){
e.preventDefault();
var schoolId= $(this).data("schoolid");
alert(schoolId);
// to do : Do something with the schoolId
});
});
Ok, so I'm trying to add voting to my website(django based) using Ajax. I have multiple entries in one page, But right now my code only let users vote on the first entry. Please help me with the code so that users can vote on all of them.
First is the html code, basically it's just a vote button for users to vote
{% for answer in answers %}<!-- django template -->
<strong id="vote_count">{{ answer.votes }}</strong> people vote this answer
{% if user.is_authenticated %}
<button id="vote" data-answerid="{{answer.id}}" class="btn btn-primary" type="button">
<span class="glyphicon glyphicon-thumbs-up"></span>
Vote
</button>
{% endif %}
{% endfor %}<!-- end django template -->
Second, below is the django view that process the request
#login_required
def vote_answer(request):
answer_id = None
if request.method == 'GET':
answer_id = request.GET['answer_id']
votes = 0
if answer_id:
answer = Answer.objects.get(id=answer_id)
if answer:
votes = answer.votes + 1
answer.votes = votes
answer.save()
return HttpResponse(votes)
below is the url mapping:
url(r'^like_category/$', views.like_category, name='like_category'),
Finally is the javascript
$('#vote').click(function(){
var answerid;
answerid = $(this).attr("data-answerid");
$.get('/vote_answer/', {answer_id: answerid}, function(data){
$('#vote_count').html(data);
$('#vote').hide();
});
});
Again, my problem is that of all the entries I have in one page, with this code I can only vote the first one. How can modify it so I can vote all of them
You need to use class instead of id on <button>, so that multiple buttons can share the same jQuery event handler.
<button class="vote" data-answerid="...">
Then you can do the following in JavaScript:
$(document).on("click", ".vote", function(){
var answerid;
answerid = $(this).attr("data-answerid");
$.get('/vote_answer/', {answer_id: answerid}, function(data){
$('#vote_count').html(data);
$('#vote').hide();
});
});
This will bind the event handler to click any <button class=vote>.
Also you should do AJAX POST instead of GET by HTTP semantics, because voting is a state changing operation. Otherwise the browser or the web proxies may cache the result (though jQuery have its own cache buster).