Google App Engine "Multiline" and JavaScript array problem - javascript

How do I convert HTML textarea (multiline) to support db.StringProperty() (without the multiline)?
I have try string.replace("\n", "<br>") but the problem is when I insert this to javascript array it give me problem.
My code as following:
class Anything(db.Model):
Str_A = db.StringProperty()
...
anything = Anything.all()
template_values = { 'anything ': anything }
path = os.path.join(os.path.dirname(__file__), 'main.html')
self.response.out.write(template.render(path, template_values))
In the Javascript
var Str_A = [];
{% for a in anything %}
Str_A.push("{{ anything.Str_A }}"); /* This line problem */
{% endfor %}

You could use db.TextProperty() which supports multi-line text by default, or db.StringProperty(multiline=True) if you need to search or sort on the Str_A property (db.TextProperty is not indexed).

Related

reuse content of part of url in html

i would like to reuse parts of the url in the content of the webpage
as example
domain.com/specialist/brand/location/
where i want to reuse "brand" multiple times in the content of the webpage
and also "location" multiple times in the content of the webpage.
first i tried it with variables
url/?specialist=brand&bezorgen=city
but this does not work with the following method, because it renders them only once
i've tried the
<script>
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const specialist = urlParams.get('specialist');
const bezorgen = urlParams.get('bezorgen');
document.getElementById("specialist").innerHtml = specialist;
document.getElementById("bezorgen").innerHtml = bezorgen;
</script>
and in the html
<span id=specialist></span>
<span id=bezorgen></span>
What would be the fastest way to get this working
technology = twig and js
Thanks in advance
Twig
As you are using a custom framework I'd suggest you to mimick the app.request.get behavior that is available in Symfony.
First create a class that delivers the same logic
Request.php
class Request {
public function __construct() {}
public function get($key) {
return isset($_GET[$key]) ? $_GET[$key] : null;
}
public function post($key) {
return isset($_POST[$key]) ? $_POST[$key] : null;
}
public function url() {
$http = 'http'.(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 's': '');
return $http.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
}
}
Register the class in twig
The easiest way to add an instance of the Request class is just to add it as a global
<?php
...
$twig->addGlobal('app', [ 'request' => new Request(), ]);
Access the class inside a template
<p>this {{ app.request.get('brand') }} bike is pretty awesome and we can deliver this at {{ app.request.get('location') }}. This {{ app.request.get('brand') }} is really trustworthy</p>
mandatory note
Please be aware it is possible that clients will try to inject/generate unsafe output. However twig will prevent this as long as you don't mark the content as safe with e.g. the filter raw
Javascript
The problem with your javascript is probably because you are creating elements with the same id over and over again, which is why only the first element with the correct id will be replaced correctly
An easy solution would be to switch to classes
var foo = 'foo';
var bar = 'bar';
document.querySelectorAll('.foo').forEach(span => {
span.innerHTML = foo;
});
document.querySelectorAll('.bar').forEach(span => {
span.innerHTML = bar;
});
span {
display: block;
}
span + span {
margin: 10px 0 0 0;
}
span.foo {
color: red;
}
span.bar {
color: green;
}
<span class="foo"></span>
<span class="foo"></span>
<span class="bar"></span>
<span class="foo"></span>
<span class="foo"></span>
<span class="bar"></span>
I might be misunderstanding, but the OP seems to ask two things: (1) how to extract info from the url -- either from within the path or the query, (2) how to alter the dom with that info.
Looking at (1), you can get a lot of information from the expression new URL(window.location.href);
// using the path
// these window-named vars to simulate the browsers' window global
let windowA = {
location: {
href: "http://example.com/specialist/mybrand/mylocation"
}
};
const urlA = new URL(windowA.location.href);
console.log(urlA.pathname.split('/').slice(-2));
// using the query
let windowB = {
location: {
href: "http://example.com/specialist/?brand=mybrand&location=mylocation"
}
};
const urlB = new URL(windowB.location.href);
const params = [urlB.searchParams.get('brand'), urlB.searchParams.get('location')]
console.log(params);
Looking at (2), the OP code looks fine, except the div's ids need to be placed in quotes...
let _window = {
location: {
href: "http://example.com/specialist/mybrand/mylocation"
}
};
const url = new URL(_window.location.href);
const components = url.pathname.split('/').slice(-2);
document.getElementById("brand").innerHTML = `<h1>${components[0]}</h1>`;
document.getElementById("location").innerHTML = `<h1>${components[1]}</h1>`;
<!-- notice the quoted id expressions -->
<div id="brand"></div>
<div id="location"></div>
twig only solution:
https://www.url.com/service/bikespecialist/trek/amsterdam/
{% set brand %}{{ request.url| split('/', 7)[5]| trim('/') }}{% endset %}
{% set location %}{{ request.url| split('/', 7)[6]| trim('/') }}{% endset %}
in the text
this {{ brand }} bike is awesome, come and buy it at {{ brand }} {{ location }}
To all who replied, many thanks! this problem had me bugged for the last couple weeks
and in the case of no brand or location in the url
{% set band %}{{ request.url| split('/', 7)[5]| trim('/') |capitalize }}{% endset %}
{% if brand is empty %}
{% set brand %}qualitybikes {% endset %}
{% endif %}
{% set loation %}{{ request.url| split('/', 7)[6]| trim('/') |capitalize }}{% endset %}
{% if location is empty %}
{% set location %}entire country {% endset %}
{% endif %}

Can you do math on variables inside double curly braces in a html script?

this is a html file i currently have:
<!DOCTYPE html>
<html>
{{unit.unit_class}}
<div id="stats"></div>
<script>
var str ="", i;
for(i = 1; i<=99; i++)
{
str = str + "<p>level " + i + ": hp {{unit.hp_current}}</p>";
}
document.getElementById("stats").innerHTML = str;
</script>
</html>
that bit in the for loop {{unit.hp_current}} is a decimal number. It's value is currently set to 0.00, which it does display on my page. I was wondering if I was able to do arithmetic on this variable inside the double curly braces. I tried doing something like {{unit.hp_current + 3}} or {{unit.hp_current}} + 3 in order for the program to display 3.00 instead of 0.00, but it doesn't seem to work. Is this something I need to make a function for instead in my views.py?
No, django template language does not support operations on variables. You will need to calculate values in-code, then pass them to the template. Another way is to use a function in a template, that would calculate the value you need:
When the template engine encounters a variable, it evaluates that
variable and replaces it with the result.
...
If the resulting value is callable, it is called with no arguments.
The result of the call becomes the template value.
https://docs.djangoproject.com/en/3.0/ref/templates/language/
Yet another option is to use filters:
https://docs.djangoproject.com/en/3.0/ref/templates/language/#filters
The vairables are directly set into the HTML using the template engine , I think you should store it in some variable and than do some other arthematic operations,
<!DOCTYPE html>
<html>
<div id="stats"></div>
<script type="text/javascript">
let template_value = "{{unit.unit_class}}";
let hp_current = parseFloat(template_value);
let str = '';
for(let i = 1; i<=99; i++)
{
str = str + `<p>level ${i} hp ${hp_current}</p>`;
}
document.getElementById("stats").innerHTML = str;
</script>
</html>
you can put this kind of substitution into your JavaScript.
It is kind of the dynamic javascript , Here we have stored the value in a variable called hp_current , Now you can use this for arthematic , Even you should use the backticks in here to concatinate the variables . Try out the code up here if it can work for you !
Here is a solution that replicates your JS purely using Django template tags
<div id="stats">
{% with ''|center:99 as range %}
{% for _ in range %}
<p>level {{ forloop.counter }}: hp {{ unit.hp_current }}</p>
{% endfor %}
{% endwith %}
</div>
As mentioned by #madhusudhan you can perform addition using filters
{{ unit.hp_current|add:forloop.counter }}

Shopify - Change text of my selectorOption product dropdown variant

I worked all day on it and impossible to figure it out so I need some help :)
I try to add some text on each variant line of my "Size" dropdown on my product page :
if the product quantity > 0 : Size + Quick Delivery
else : Size + 2-3 weeks delivery
Just want to display it to the customer before the click, so I don't want it just on the selectedVariant.
I tried to change it by my script.js, I was thinking to :
copy each variant quantity (I didn't find the way to do it)
copy my Dropdown in a list value/key + add text (Quick/2-3 weeks) depending of the variant quantity
var optionsSizes = {};
var optionsSizes = {};
$('#mySizes option').each(function(){
optionsSizes[$(this).val()] = $(this).text() + variant.inventory_quantity;
});
//console.log(optionsSizes);
var $el = $("#mySizes");
$el.empty(); // remove old options
$.each(optionsSizes, function(value,key) {
$el.append($("<option></option>")
.attr("value", value).text(key));
});
The copy/paste of the dropdown work but that's all.
It was easy to do it on variantSelected but that's not what I want.
Please feel free to ask if you have any question.
Cheers,
bkseen
('#product-select-5916642311-option-0') and $('#mySizes') this select elements are not in your theme by default. A Shopify or theme script adds these two elements based on the product's JSON information available via Shopify. Hence there is no direct way to get the desired result.
Here's the trick that can achieve what you desire.
Load all the variants and their required properties into a JSON object. To do this add <script>variantsJSON = {}</script> at the top of the liquid file.
Now load the variants in the following structure:
variantsJSON = {
"variant_option1" : {
"variant_option2_1_title" : "variant_option2_1_quantity",
"variant_option2_2_title" : "variant_option2_2_quantity",
} ....
}
To get the above structure, you need to add the following script inside {% for variant in product.variants %} or a similar loop in your liquid file.
<script>
if (!variantsJSON['{{ variant.option1 }}']){
variantsJSON['{{ variant.option1 }}'] = {}
}
{% assign availability = 'QUICK DELIVERY' %}
{% if variant.inventory_quantity == 0 %}{% assign availability = '2-3 WEEKS DELIVERY' %}{% endif %}
if (!variantsJSON['{{ variant.option1 }}']['{{ variant.option2 }}']){
variantsJSON['{{ variant.option1 }}']['{{ variant.option2 }}'] = '{{ availability }}'
}
</script>
The above snippet (possible refinement required) will load all the variants and their availability into the JSON object
Now all you need to do is trigger a function on change of $('#product-select-{{ product.id }}-option-0') which will clear all <li>s in $('#mySizes'), then populates them using the values stored in variantsJSON's variant_option2 & variant_availability of the selected variant_option1
P.S. Feel free to format my answer. I'm somehow unable to get the right formatting.
To answer Hymnz on
That's tricky but I think I can help. How are you changing the span with the classes product__inventory-count product__form-message--success ? – HymnZ 10 hours ago
Blockquote
if (variant) {
{% if settings.product_show_shipping %}
var myCount = variant['inventory_quantity'];
var myPath = this.element.find('.product__inventory-count');
if (myCount < 1){
myPath.removeClass('product__form-message--success');
myPath.addClass('product__form-message--error');
myPath.text("2-3 weeks delivery");
}else{
//myPath.toggleClass('product__form-message--success').siblings().removeClass('checked');
myPath.removeClass('product__form-message--error');
myPath.addClass('product__form-message--success');
myPath.text("Quick delivery");
}
{% endif %}
The thing is, variant is the variant selected and not going through all the product's variants.

Django: Referencing Views List in Java Script?

So I'm working with Django on a website that I am playing around with, and have been trying to research how I could get the following list in my views.py and be able to reference it in my javascript? I'm working on creating an ajax call and the tutorials I am coming accross are a bit confusing.
#lines 6 - 8 of my code.
def catalog_home(request):
item_list = item.objects.order_by('name') #item is the model name
note: the item model containts a name, description, overview and icon column.
Is it possible for me to use the list above (item_list) and be able to write a javascript function that does something similar to this? :
$(document).ready(function() {
$("#showmorebutton").click(function() {
$("table").append("<tr></tr>");
for (var i = 0; i < 3; i++) {
var itemdescription = item.description;
var itemName = item.name;
var icon = item.icon;
$("table tr:last").append(generateCard(itemName,
itemdescription,
icon));
}
function generateCard(itemNameC, itemdescriptionC, iconC) {
var card = "<td class='tablecells'><a class='tabletext' href='#'><span class='fa "
+ iconC
+ " concepticons'></span><h2 class='header'>"
+ itemNameC
+ "</h2><p>"
+ itemdescripionC
+ "<span class='fa fa-chevron-circle-right'></span></p></a></td>";
return card;
}
I don't mean to crowd source the answer to this, I just would appreciate any feedback/advice for me to handle this task, as I am fairly new to coding.
You should absolutely be able to do this. The trick is to understand Django templates. You showed part of the view but you will need to render to a template. Inside the template, you can just do something like
HTML code for page goes here (if you're mixing js and html)
<script>
var items = [{% for d in data %}
{% if forloop.last %}
{{ d }}
{% else %}
{{ d }},
{% endif %}
{% endfor %}];
// code that uses items
</script>
Note there's a little bit of work required to make sure you have the right # of commas [taken from this SO answer and your code should handle the case where the array is empty.
Alternatively, you could do an ajax call from static javascript to your django server using something like django rest framework to get the list of items as a json object.

New forms - embedding a collection of forms - Symfony2

I'm doing the same as explained here: http://symfony.com/doc/current/cookbook/form/form_collections.html
But in my case I want to add new "tags" not manually with clicking on a link, but automatically. I give to my template an array with items and for each of this items I want to add a new form - the number of items should be equal to the number of forms.
If it's possible, I'd prefer a solution like this:
{% for i in items %}
{{ i.name }} {{ form_widget(form.tags[loop.index0].name) }}
{% endfor %}
But how to automatically create objects in the controller, too? It tells me that there is no obeject with index=1, and yes - there isn't, but isn't there a way to create them automatically and not need to create for example 10 empty objects of the same kind in my controller? :(
Another thing I was thinking was something like this:
{% for i in items %}
<ul class="orders" data-prototype="{{ form_widget(form.orders.vars.prototype)|e }}">
{{ i.name }} and here should be a field from the form, for example tag.name
</ul>
{% endfor %}
I suggest that the js given in the cookbook should be changed to do this, but I'm not good in js and my tries didn't do the job.
I tried putting this in the loop:
<script>
addTagForm(collectionHolder);
</script>
and this in a .js file:
var collectionHolder = $('ul.orders');
jQuery(document).ready(function() {
collectionHolder.data('index', collectionHolder.find(':input').length);
function addTagForm(collectionHolder) {
var prototype = collectionHolder.data('prototype');
var index = collectionHolder.data('index');
var newForm = prototype.replace(/__name__/g, index);
collectionHolder.data('index', index + 1);
var $newFormLi = $('<li></li>').append(newForm);
}
});
Assuming that your main class has addTag($tag) method, you can add different 'new' tags to it.
In class Task
public function addTag($tag){
$this->tags[]=$tag;
return $this;
}
In your Controller (assuming 10 tags here)
$task=new Task();
for($i=0;i<10;i++){
$task->addTag(new Tag());
}
$form->setData($task);
In your view
{% for tag in form.tags %}
<ul class="orders">
<li>{{ form_widget(tag.name) }}</li>
</ul>
{% endfor %}
If you don't need the manually click, you can remove the JavaScript part.

Categories

Resources