Octobercms Component Twig - javascript

Can someone show me how to set unique Id for components?
I only know I have to put this code in my default.htm
{% set uid = '{{__SELF__.id}}' %}
how to use it in javascript?
and what is this for?
var avatar_{{uid}} = {{ avatar }};
for example this is my js
$(function(){
$("#tab-close").click(function() {
$("#tab").addClass("hidden");
});
});
How do I set a unique Id for it so that when I duplicate the component both can still work normally without errors?

It might be better to encapsulate your control with a single identifier, like this
<div id="mycontrol{{ __SELF__.id }}">
...
</div>
Then in JavaScript, you can target elements inside:
function initTabs(controlEl) {
var $control = $(controlEl)
$(".tab-close", $control).click(function() {
$(".tab", $control).addClass("hidden");
});
}
The code above targets the class names found only inside the $control container. You would call this function from the markup like so
<script>
$(function(){
initTabs('#mycontrol{{ __SELF__.id }}');
});
</script>

Related

Need Advice in Javascript - New font family for every div

I'm making a post site, but I'm trying to make each post have it's own individual font family.
You can see here with the cursive font, it is assigning it properly, but to all of a class. I need to break each post into it's own individual iteration.
Since I am doing it on load, i can't seem to grab their Id's or Attributes easily and put them into an array.
my current solution is something like this, full code below
The randfontlist doesn't return a normal object, it returns something I've never seen before, like the entire post or something.
Does anyone have a smart solution to iterate through the items with .randfont tag?
Thank you
randfontlist = $('.randfont').toArray()
randfont_idlist = $('.randfont').attr("id").toArray()
$(`.randfont`)[i].addClass(random)
.html
{% for poopfact in poopfacts %}
<div class="col">
<div class="row">
<p>{{ poopfact.date }} </p>
<p class="randfont randfont{{poopfact.id}}" id="{{poopfact.id}}">{{ poopfact.fact }}</p>
<p> {{ poopfact.author }}</p>
</div>
.script
$( document ).ready( function() {
$('.randfont').load(randomizeFonts())
function randomizeFonts() {
let fonts = ['caveat', 'indieflower', 'nanum', 'pacifico', 'pmarker', 'tangerine'];
const randfonts = $('.randfont')
for (let i = 0; i < randfonts.length; i++) {
var random = fonts[Math.floor(Math.random() * fonts.length)];
//get the ids of those items and put it into another array
$(`.randfont`).addClass(random)
}
}
Assuming every font name in the fonts array has its equivalent CSS class to set the font-family...
$( document ).ready( function() {
const fonts = ['caveat', 'indieflower', 'nanum', 'pacifico', 'pmarker', 'tangerine'];
$('.randfont').each(function(index, element){
$(element).addClass(fonts[Math.floor(Math.random() * fonts.length)])
})
}

How to modify Django template variable with JS and return it changes on it

I would like to pass a list of ids to a view when i click on a link:
<a href="{% url 'app:manage_ids' %}?ids={{ids}}">
So i have created a template var and pass it to js:
{% with ids="" %}
<script type="text/javascript">
window.ids = "{{ ids }}";
</script>
{% endwith %}
I manage object ids when click on checkbox:
<input type="checkbox" class="checkbox" value="{{ object.id }}">
Adding or removing it to a list:
$('.checkbox').change(function() {
var id = $(this).val();
// if django template var is empty
var list_ids = [];
// else
var list_ids = window.ids;
if ($(this).is(':checked')) {
list_ids.push(id);
// here i have to save it on a django template var to use it on the click link
}
else {
const index = list_ids.indexOf(id);
if (index > -1) {
list_ids.splice(index, 1);
// here i have to save it on a django template var to use it on the click link
}
}
});
Anybody could help me about how to do it ?
Thanks you so much.
You cant update the django variable and expect it to update your href value of the link.
Moreover, you should not send the value of a GET query parameter as a list datastructure, instead you'll send it as ?ids=<value1>&ids=<value2>
To do this you'll have to first construct such string of url and then dynamically update the href of your hyperlink with it.
You can first decalre the string variable for you href in javascript somehwere as:
var id_link = "{% url 'app:manage_ids' %}?ids=";
Then whenever the click checkbox function is called you can add new value to this and update the href of link:
id_link += "&ids=" + id;
Add an id to your href and get it and update it
var a = document.getElementById('yourlinkId');
a.href = id_link
Now when someone clicks this link, you can get these in query parmeters in view as:
request.GET.getlist('ids')
and you shall get list of all IDs.
Note (My two cents): Ideally in a good archiecture this should happen by clicking a button with a post request from template in django.

How to select elements from a handelbars template?

We have a div within our webpage:
<div id="person-details">
<div></div>
...
</div>
We select the relevant elements from this div using the following jQuery code:
var person = $("#person-details");
var children = release.find("div");
var fullname = children.first();
We use a render function to perform an ajax request to get a handlebars template that we're storing in an external file:
function _render() {
var templateScript;
template.getTemplate(filename).done(function(template) {
templateScript = Handlebars.compile(template);
fullname.html(templateScript(context));
});
}
The template looks like the following:
<div>
<div>
<p>{{name}}</p>
</div>
<div>
<p>{{value}}</p>
</div>
</div>
After the render function has been called, we want to select any of the elements from within the template. For example we have tried using:
fullname.children('div');
but as the content has been dynamically generated we aren't able to get the nodes from within the DOM.
Is it even possible to select elements from within a generated handlebars template like this?
Thanks to #DanielShillcock for highlighting render() being asynchronous. Here is a solution:
function _render() {
var templateScript;
template.getTemplate(filename).done(function(template) {
templateScript = Handlebars.compile(template);
selector.html(templateScript(attribute));
value = selector.find("div");
});
}

How to display value of a ViewBag in my view with a JS function?

I want to display the data from a ViewBag in my View with Javascript. Here is my code.
View
<span id='test'></span>
Javascript
function myFunction()
{
$('#test').text('#ViewBag.Test');
}
When myFunction() is called I get the text #ViewBag.Test but not his value. How can I fix this ?
You need to place your JavaScript which takes the #ViewBag.Test value in a page which is interpreted by the Razor view engine. My guess is that this is currently not the case.
If you want to keep your javascript codebase separate from the view (which is entirely reasonable) you can use a global variable:
// in the view:
var testText = '#ViewBag.Test';
// in external js
function myFunction() {
$('#test').text(window.testText);
}
Alternatively, you can use a data-* attribute:
<span id='test' data-text="#ViewBag.Test"></span>
// in external js
function myFunction() {
$('#test').text(function() {
return $(this).data('text');
});
}
What you should be ideally doing is passing the data to the view with a view model. Have a property to store that value you want to pass. For example. Let's think about a page to show the customer details and you want to get the last name in your javascript variable.
Your GET action method
public ActionResult View(int id)
{
var vm=new CustomerViewModel();
vm.LastName="Scott"; // You may read this from any where(DAL/Session etc)
return View(vm);
}
and in your view which is strongly typed to your view model.
#model CustomerViewModel
<div>
Some Html content goes here
</div>
<script type="text/javascript">
var lastName="#Model.LastName";
//Now you can use lastName variable
</script>
EDIT : (As per the question edit) To show the content on some event (ex : some button click), Store the value somewhere initially and then read it as needed and set it wherever you want.
#model CustomerViewModel
<div>
<span id="content"></span>
#Html.HiddenFor(s=>s.LastName)
<input type="button" id="btnShow" value="Show content" />
</div>
<script type="text/javascript">
$(function(){
$("btnShow").click(function(e){
$("#content").html($("#LastName").val());
});
});
</script>
Firstly make sure your ViewBag.Test does got a value, then use a div tag instead of a span and add the following code:
<script type="text/javascript">
$(document).ready(function () {
StartRead();
});
function StartRead() {
document.getElementById("test").innerHTML = '#ViewBag.Test';
}
</script>

A better way to pull an ID from a form submission Javascript/Django

Currently what I have coded up works, but it seems rather crude. Basically here's what I have (simplified):
JQuery ready:
<script type="text/javascript">
$(document).ready(function() {
$('div.partDelete').click(function() {
// TODO this seems like a dirty hack
var split = this.id.split('_');
if(split.length == 3) {
$('#part_id').val(split[0]);
alert($('#part_id').val());
$('#removePartForm').submit();
} else {
alert('There was a problem removing the selected part');
}
});
</script>
The form I am using:
<form id="removePartForm" action="{% url remove_part %}" method="post">
<input type="hidden" id="part_id" name="part_id" value="-1" />
{% for part in current_build.parts.all %}
<div id="{{ part.id }}_part_id" class="partDelete">remove</div>
{% endfor %}
</form>
All I'm trying to do is set the hidden input to take the part.id that has been selected by the user so that I can use it in my views.
For all I know this is the correct way to go about this, but I just have a feeling it isn't. I am new to Django & JQuery so there may be some built in functionality for this that I haven't found yet.
Thanks for any suggestions that you may have!
Solution (see mikaelb's answer below)
Javascript:
$('div.partDelete').click(function() {
var selected_id =$(this).data("id");
$('#part_id').val(selected_id);
$('#removePartForm').submit();
});
HTML changes:
<div class="partDelete" data-id="{{ part.id }}">remove</div>
First of all; IDs shouldn't start with a number (http://www.w3.org/TR/html4/types.html#type-name).
Aside from that, you'd typically use the data-* attribute for setting IDs to communicate with JS from server side. The data-* attribute can be anything you want. So data-foo="" is a valid attribute.
Example:
HTML:
<div class="item" data-id="{{ part.id }}">
<p>Foo</p>
</div>
Javascript:
$(function () { // same as document read
$(".button-class").on("click", function () {
// Here "this" will be the element
var id = $(this).data("id"); // same as getting attribute data-id
// Could also use $(this).attr("data-id")
});
});
Hope this helps.
Edit: Moved comment to make it more clear, changed the example to be more specific to OP's problem.

Categories