Javascript doesn't refresh in Django loop - javascript

I have a Django template (html), and a javascript in it that I want to loop for various pair values. It doesn't loop.
Here is the code in the template rsmgui.html:
{% for field in elements %}
<input type="hidden" id="theFieldLabelID" name="theFieldLabel" value="{{ field.label }}">
<input type="hidden" id="theFieldID" name="theField" value="{{ field }}">
<script src="{{ STATIC_URL }}js/loadStorage.js"></script>
{% endfor %}
The javascript loadStorage.js looks like this:
var myFieldLabel=document.getElementById("theFieldLabelID").value.replace(/ /g,"")
var myField = document.getElementById("theFieldID")
alert("Label = " + myFieldLabel);
localStorage.setItem(myFieldLabel, JSON.stringify(myField));
But it doesn't loop, it gets the first pair and then repeats it for the number of pairs. Any ideas how to "flush" the javascript so it reloads each time?

it gets the first pair and then repeats it for the number of pairs
That is because getElementById only returns first element. Element ID should be unique across the page. Without changing your logic, there are two solutions below.
First one is to add loop counter suffix:
{% for field in elements %}
<input type="hidden" id="theFieldLabel{{ forloop.counter }}" name="theFieldLabel" value="{{ field.label }}">
<input type="hidden" id="theField{{ forloop.counter }}" name="theField" value="{{ field }}">
<script>var id_suffix = "{{ forloop.counter }}"</script>
<script src="{{ STATIC_URL }}js/loadStorage.js"></script>
{% endfor %}
var myFieldLabel=document.getElementById("theFieldLabel" + id_suffix).value.replace(/ /g,"")
var myField = document.getElementById("theField" + id_suffix)
alert("Label = " + myFieldLabel);
localStorage.setItem(myFieldLabel, JSON.stringify(myField));
Second one is to use getElementsByName:
{% for field in elements %}
<input type="hidden" id="theFieldLabelID" name="theFieldLabel" value="{{ field.label }}">
<input type="hidden" id="theFieldID" name="theField" value="{{ field }}">
<script>var index = {{ forloop.counter0 }}</script>
<script src="{{ STATIC_URL }}js/loadStorage.js"></script>
{% endfor %}
var myFieldLabel=document.getElementsByName("theFieldLabel")[index].value.replace(/ /g,"")
var myField = document.getElementsByName("theField")[index]
alert("Label = " + myFieldLabel);
localStorage.setItem(myFieldLabel, JSON.stringify(myField));
Considering #sytech comment, you can wrap your code into function with a parameter is the index/id_suffix. Then call it with necessary value.
<script src="{{ STATIC_URL }}js/loadStorage.js"></script>
{% for field in elements %}
<input type="hidden" id="theFieldLabel{{ forloop.counter }}" name="theFieldLabel" value="{{ field.label }}">
<input type="hidden" id="theField{{ forloop.counter }}" name="theField" value="{{ field }}">
<script>loadStorage("{{ forloop.counter }}");</script>
{% endfor %}
function loadStorage(id_suffix)
{
var myFieldLabel=document.getElementById("theFieldLabel" + id_suffix).value.replace(/ /g,"")
var myField = document.getElementById("theField" + id_suffix)
alert("Label = " + myFieldLabel);
localStorage.setItem(myFieldLabel, JSON.stringify(myField));
}

Related

Suggest a product X on a lower price when product Y is in cart

In Shopify, when cart has item.product_id == 8078327054657, a form will show suggesting to add item.product_id == 8095240388929. However, it doesn't seem to add the item and only checks out when I click the 'Add' button.
I have included the Liquid and HTML codes for the form and the JS codes for the product to be added to cart when button is clicked. It's basically an upsell. Please help me make it work. Thanks
<div class="cart--upsell-es">
{% if cart.item_count > 0 %}
{% for item in cart.items %}
{% if item.product_id == 8078327054657 %}
{% assign in_cart = true %}
{% endif %}
{% endfor %}
{% endif %}
{% if in_cart %}
<div class="cart--upsell-es">
<div style="padding: 20px 0">
<p stye="text-align:center; font-weight:800">Upgrade and Save $41</p>
</div>
<div class="upsell-wrapper">
<form
id="upsell-form"
action="/cart/add"
method="post"
enctype="multipart/form-data">
<input
type="hidden"
name="id"
value="8095240388929" />
<input
type="hidden"
name="quantity"
value="1" />
<img src="https://cdn.shopify.com/s/files/1/0699/3615/2897/files/DTB-BEIGE-min.png?v=1674021338"
width="50px"
height="50px" />
<label for="upsell">Double Trouble Bundle</label>
<button
id="upsell-btn"
type="submit"
value="Add">Add</button>
</form>
</div>
</div>
{% endif %}
</div>
```
```
<script>
if (theme.settings.cart_type === "drawer") {
document.getElementById("upsell-btn").addEventListener("click", function() {
var form = document.querySelector("cart--form");
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/cart/add.js");
xhr.onload = function() {
var item = JSON.parse(xhr.responseText);
var xhr2 = new XMLHttpRequest();
xhr2.open("POST", "/cart/change.js");
xhr2.onload = function() {
var item2 = JSON.parse(xhr2.responseText);
console.log(item2);
};
xhr2.send(JSON.stringify({quantity: 0, id: 8078327054657}));
};
xhr.send(formData);
});
}
</script>
```

How to implement predictive search into Shopify store

I'm trying to implement predictive search into the search bar on the store, however I'm having abit of trouble making sense of the docs.
Here's what I've got so far, hopefully someone can point me in the right direction with what it is I am missing:
%- if settings.predictive_search_enabled -%}
<predictive-search data-loading-text="{{ 'accessibility.loading' | t }}">
{%- endif -%}
<form action="{{ routes.search_url }}" method="get" role="search">
<ul>
<li>
<input
type="search"
name="q"
placeholder="Amp Hours (aH)"
class="amp-input"
value="{{ search.terms | escape }}"
{%- if settings.predictive_search_enabled -%}
role="combobox"
aria-expanded="false"
aria-owns="predictive-search-results-list"
aria-controls="predictive-search-results-list"
aria-haspopup="listbox"
aria-autocomplete="list"
autocorrect="off"
autocomplete="off"
autocapitalize="off"
spellcheck="false"
{%- endif -%}>
{%- if predictive_search.performed -%}
<ul class="amp-dropdown-container">
{%- if predictive_search.resources.products.size > 0 -%}
<h5 class="volt-options-title">Top Searches</h5>
{%- endif -%}
{%- for product in predictive_search.resources.products -%}
<li>
{{ product.title }}
</li>
{%- endfor -%}
</ul>
{%- endif -%}
</li>
</ul>
</form>
{%- if settings.predictive_search_enabled -%}
</predictive-search>
{%- endif -%}
A predictive search box shows up but its not the way I need it to be. (only want it displaying products, not pages collections etc aswell).
I've also seen the javascript below in other tutorials but dont know how to use it for what I need. Any suggestions?
<script>
var q = 'goki'
var b = '&resources[type]=product'
$.ajax('/search/suggest.json?q=' + q + b,{
type: 'GET',
dataType: 'json', // added data type
success: function(response) {
console.log(response);
var productSuggestions = response.resources.results.products;
if (productSuggestions.length > 0) {
var firstProductSuggestion = productSuggestions[0];
alert(firstProductSuggestion.body);
}
}
});
</script>

form wizard does not move to the next screen in a jquery dialog

I an using django-crispy forms and using that in a jquery dialog box to show a form wizard. the problem that I am facing is that when used in the dialog box the wizard never moves to the next screen.
So, my wizard is defined as follows:
class ContactWizard(SessionWizardView):
def get_template_names(self):
return "reviewdialog.html"
def done(self, form_list, **kwargs):
return HttpResponseRedirect('index')
And the template is defined as:
{% load crispy_forms_tags %}
{% load i18n %}
{% block content %}
<form action="." method="post">
{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% crispy form %}
{% endfor %}
{% else %}
{% crispy wizard.form %}
{% endif %}
{% if wizard.steps.prev %}
<button name="wizard_goto_step" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
<button name="wizard_goto_step" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
</table>
<input type="submit" class="btn btn-success" value = "NEXT">
</form>
{% endblock %}
Now, I show this in a jquery dialog where I have overridden the submit method to ensure that the dialog does not close on clicking the 'NEXT' button
<script>
function EditDialog(pk) {
$.ajax({
url: "{% url 'populatereviewform' %}",
method: 'GET',
data: {
pk: pk
},
success: function(formHtml){
//place the populated form HTML in the modal body
$('.modal-body').html(formHtml);
$( "#dialog" ).modal({width: 500, height: 500});
},
dataType: 'html'
});
$('#dialog').submit( function(e) {
return false;
});
return false;
}
</script>
The AJAX part just populates the form with some data and the dialog object is a standard jquery modal dialog. The form is shown at the first screen and is populated with the correct value but when I press NEXT nothing happens in the sense that the wizard does not transition.
The urls.py is configured as:
url(r'^review/(?P<pk>\d+)/$', views.ContactWizard.as_view([DummyForm, OtherForm]), name='review'),
Som, the form starts with the DummyForm (which is a ModalForm) but does not progress to the next wizard screen. I have a feeling it could be something to do with my javascript but could bit get to the bottom of this.
EDIT
So, based on #udi's answer, I tried the following:
$("#dialog").submit(function(e)
{
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
var postData = $(this).serializeArray();
var formURL = $(this).attr("action");
$.ajax(
{
url : formURL,
type: "POST",
data : postData,
success:function(data, textStatus, jqXHR)
{
$('.modal-body').html(data);
},
error: function(jqXHR, textStatus, errorThrown)
{
alert(errorThrown)
}
});
e.preventDefault(); //STOP default action
e.unbind(); //unbind. to stop multiple form submit.
});
return false;
}
However, the data that is returned here is not the next screen of the wizard but the underlying page on which the dialog is shown. So, perhaps it is the formURL or postdata variables that are not initialized properly?
The template for the wizard screen is:
{% load crispy_forms_tags %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<form id="review-form" action="." method="post">
{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% crispy form %}
{% endfor %}
{% else %}
{% crispy wizard.form %}
{% endif %}
{% if wizard.steps.prev %}
<button name="wizard_goto_step" class="btn btn-success" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
<button name="wizard_goto_step" class="btn btn-success" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
</table>
<input type="submit" class="btn btn-success" value = "Hello">
</form>
{% endblock %}
You will need to get the html of the next form via jQuery and update it in the dialog.

Uncaught ReferenceError: $ not defined

I know there are lot of questions with the same tag. But I tried few solutions of them and it didn't worked. Following is my code and I can't figure out how to fix it.
<script>
function setPrice(){
var price = $(".variation_select option:selected").attr("data-price")
var sale_price = $(".variation_select option:selected").attr("data-sale-price")
if (sale_price != "" && sale_price != "None" && sale_price != null ) {
$("#price").html("<h3>" + sale_price + " <small class='og-price'>" + price + "</small></h3>");
} else {
$("#price").html(price);
}
}
setPrice()
$(".variation_select").change(function(){
setPrice()
})
$("#submit-btn").click(function(event){
event.preventDefault();
var formData = $("#add-form").serialize();
console.log(formData);
$.ajax({
type:'GET',
url: "{% url 'cart' %}",
data: formData,
success: function(data){
console.log(data)
},
error: function(response, error){
console.log(response)
console.log(error)
}
})
// $("#add-form").submit()
})
</script>
Error it shows on browser inspect elements is at
var price = $(".variation_select option:selected").attr("data-price")
Even though I don't think its necessary but following is the HTML code:
<div class='col-sm-4'>
<form id='add-form' method='GET' action="{% url 'cart' %}">
<p id='jquery-message' class='lead'>
</p>
{% if object.variation_set.count > 1 %}
<h3 id='price'>{{ object.variation_set.first.price }}</h3>
<select name='item' class='form-control variation_select'>
{% for vari_obj in object.variation_set.all %}
<!-- <option data-img="http://www.spirit1059.com/pics/Feeds/Articles/2015611/118317/Beach.jpg" data-price="{{ vari_obj.price }}" value="{{ vari_obj.id }}">{{ vari_obj }}</option> -->
<option data-sale-price="{{ vari_obj.sale_price }}" data-price="{{ vari_obj.price }}" value="{{ vari_obj.id }}">{{ vari_obj }}</option>
{% endfor %}
</select>
{% else %}
<input type="hidden" name='item' value='{{ object.variation_set.first.id }}' />
<h3 id='price'>{% if object.variation_set.first.sale_price %}
{{ object.variation_set.first.sale_price }}
<small class='og-price'>{{ object.variation_set.first.price }}</small>
{% else %}
{{ object.variation_set.first.price }}
{% endif %}
</h3>
{% endif %}
<br/>
<input class='form-control' type='number' name='qty' value='1' />
<br/>
<input id='submit-btn' type='submit' value='Add to Cart' class='btn btn-default' />
</form>
Jquery Script file includes following:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{% static 'js/ie10-viewport-bug-workaround.js' %}"></script>
Please ignore Django template language if you are not familiar with it. You can still have the idea about jQuery error skipping the template language.
after using jquery script, use this code instead:
$(document).ready(function(){
setPrice()
$(".variation_select").change(function(){
setPrice()
})
});
If you're using jQuery in your page you need to include a jquery liberary in your html page. Because initially in javascript $ is nothing but $ means jquery which tells the browser that its a jquery function.
Include this jquery liberary in your webpage.
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
add jQuery script before your JS code
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
define variable "$". You can achieve this by adding a wrapper to your JS code:
<script>
(function($){
// your code here
})(jQuery)
</script>
MMh try including jquery before your tag
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

Send only specific value to server in Django

I have a html code like this:
{% for i, j, k in full_name %}
{{ i }} {{ j }}
<input type="text" name="follow_id" value="{{ k }}" />
<input type="submit" value="Follow"><br /> <br />
{% endfor %}
The output looks like this:
user1 user_id_of_user1 follow_button
user2 user_id_of_user2 follow_button
user3 user_id_of_user3 follow_button
If I press the follow button of user3 I want to send the id of user3 only so that I can access it in server like this:
followed_user = request.POST['follow_id']
# Process
But, no matter which follow_button I press, I get the user id of only user1. How to fix this?
This is not a Django issue, but a HTML issue. Here is the work around: 1 form for each user:
{% for i, j, k in full_name %}
<form action="mydomain.com/mysubmiturl/" method="POST"><!-- Leave action empty to submit to this very same html -->
{% csrf_token %} <!-- Django server only accept POST requests with a CSRF token -->
{{ i }} {{ j }}
<input type="text" name="follow_id" value="{{ k }}" />
<input type="submit" value="Follow"><br /> <br />
</form>
{% endfor %}
Note that all the forms submit to the same URL, and thus the same view function !
Just my 2 cents, I would use some jQuery for this job.
In your template:
{% for i, j, k in full_name %}
{{ i }} {{ j }}
Follow
{% endfor %}
Then submit the data using AJAX:
$('.follow-button').click(function (e) {
e.preventDefault();
var this_id = $(this).attr('id').replace('js-follow-', '');
$.ajax({
type: 'POST',
url: 'path/to/view',
data: {'follow_id': this_id},
success: function (resp) {
// do something with response here?
}
});
});

Categories

Resources