Im working on an interactive gantt chart with django and jquery.
I build the table like this:
<div class="gantt">
<div class="gantt-labels">
{% for item in items2 %}
<tr>
<div class="gantt-labels" id="labels"> </div>
</tr>
{% endfor %}
</div>
<div class="gantt_timeline">
<div class="table gantt_table" id="myTable">
<thead>
<div class="gantt-tr time-bar">
{% for item in items2 %}
<div class="gantt-td chart-values">{{ item.y|date:"D" }}</div>
{% endfor %}
</div>
</thead>
<tbody>
{% include "datamodel3.html" %}
{% for item in items2 %}
<div class="tr gantt-tr rows" id="row{{ forloop.counter }}" >
{% for item in items2 %}
<div class="td gantt-td"> </div>
{% endfor %}
</div>
{% endfor %}
</tbody>
</div>
</div>
</div>
The queryset "items2" holds the data for the table (amount of rows and cells in dates)
Example:
row1 01/01/2012
row2 02/01/2012
...
row31 31/01/2012
datamodel3.html
Here are the bars:
{% for item in items3 %}
<div class='bar resizable bars' style="pointer-events:visible;" id="bar{{ forloop.counter }}" data-duration="{{ item.start|date:'D' }}-{{ item.end|date:'D' }}">
<div class='resizers'>
<div class='resizer top-left'></div>
<div class='resizer top-right'></div>
<div class='resizer bottom-left'></div>
<div class='resizer bottom-right'></div>
</div>
</div>
{% endfor %}
The queryset "items3" holds the data for the bars (name, start- and finish-date)
Example:
bar1 01/01/2012 10/01/2012
bar2 08/01/2012 14/01/2012
I use this to make the bars draggable:
(function() {
$(".bar").draggable({
containment: "parent"
});
})();
I use this to make the bars resizable:
https://codepen.io/ZeroX-DG/pen/vjdoYe
I use this to schedule them:
https://codepen.io/tutsplus/pen/ZEzerNB
I use this to assign a label to each row:
var iLabel = 0;
document.querySelectorAll('#labels').forEach(function (element, index) {
element.innerHTML = iLabel < labels.length ?
labels[iLabel] :
'';
iLabel++;
})
So far, the bars have the right length (start and finish date), are draggable and resizable.
The only thing for now is to append each bar to its row (first bar to first row and so on....)
I tried different ways, but ended up assigning each row and bar an ID and attaching them to one another:
$(document).ready(function(){
newfunction();
});
function newfunction(){
var thisrows = $("#row1");
var thisbars = $("#bar1");
/* var fragment = document.createDocumentFragment(); fragment.appendChild(thisbars); */
$(thisrows).html(thisbars);
}
When I try to use fragments, I get: TypeError: Argument 1 ('node') to Node.appendChild must be an instance of Node.
Now, instead of hard-coding every id, I tried to do something like this:
function newfunction(){
var n = 0;
var e = 0;
$(".rows").each(function(){
var thisrows = $(this).attr("id") + n;
n++;
});
$(".bars").each(function(){
var thisbars = $(this).attr("id") + e;
var fragment = document.createDocumentFragment();
fragment.appendChild(thisbars);
e++;
});
$(thisrows).appendChild(fragment);
};
Which doesnt work, even without using fragments. Any suggestions?
Also, I want to save the new position and length of the bar when I move/resize it.
What would be the best approach to do this?
Thank you in advance
Here is my first post about this with an image of the table:
Django + JQuery - Append bars to table rows
I am not entirely sure I get the entire context but I think there some errors in the code, here is my attempt to resolve the script:
The only thing for now is to append each bar to its row (first bar to first row and so on....)
function newfunction(){
const bars = $(".bars");
$(".rows").each(function(index){
$(this).html(bars[index]);
});
};
To save the new position and length of the bar when I move/resize it, boils down to having an object with unique id for the bar { [bar id]: { position: ... , size: .... }, ...} or straight up array of bars [{ id: ..., size: ... } , ...] where you can easily switch positions. You update the object in the observer/listener.
Related
I have developed a web app using Django.
I have created a table pagination.
how could I create a search input for all the data in all the pages of table?
view.py
def Browse_and_adopt(request):
Title_list = Title.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(Title_list, 10)
try:
Titles = paginator.page(page)
except PageNotAnInteger:
Titles = paginator.page(1)
except EmptyPage:
Titles = paginator.page(paginator.num_pages)
page_obj = paginator.get_page(page)
return render(request, 'bms/inbox/Browse_and_adopt.html', {'Titles': Titles, 'page_obj': page_obj})
Browse_and_adopt.html
<table id="myTable">
<thead>
<tr>
<th>Title</th>
</tr>
</thead>
<tbody>
% for book in page_obj %}
<tr>
<td>{{ book.title }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div>
Now only the first page shows, how to create a search bar for all the data in the table?
The view does not know whick object you are looking for.
There is two ways to do so.
In the frontend end where you write a JS callback event listener that filter all the supplied table data. " not optimal ''
Or you can create a custom view that recieve the object pk via post request and return the filtered result e.g url :
urlpatterns = [
path('update/<int:pk>/', updateViewSet.as_view()),
]
This is my drop down
<div class="dropdown" >
<button onclick="myFunction()" class="dropbtn">Course List</button>
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
{% for list in list1%}
<a id="courseName" onclick="addCourse()"> {{list.courseName}}</a>
{% endfor %}
</div>
</div>
here i am trying to access value of the selected course name
function addCourse() {
var x = document.getElementById("courseName").value
document.getElementById("demo").innerHTML = x;
}
But this is giving me "undefined" as a result.
looks like you are running a loop, don't use the id for multiple elements, Id's must be unique, instead use classes.
not sure what what language you are using, laravel? anyway try this.
{% for list in key=>list1%}
<a class="courseName" onclick="addCourse(e)"> {{list.courseName}}</a>
{% endfor %}
</div>
function addCourse(e){
var x = e.target.textContent
document.getElementById("demo").innerHTML = x;
}
I think you want a dynamic element
` {% for list in list1%}
<a id="courseName" onclick="addCourse(this)" name ={{list.courseName}} >
{{list.courseName}}</a>`
{% endfor %}
function addCourse(obj){
var x = $(obj).attr("name");
alert(x);
}
`
Basically I have to develop a Tic-Tac-Toe game, here is the HTML file which I can't rewrite only reformat a bit, but the idea should stay the same.
{% block content %}
<nav class="navbar fixed-top navbar-light">
<button id="retry-button" class="btn btn-success">Try again?</button>
Reset settings
</nav>
<div id="game-board" class="mb-3" data-row-num="{{ row_num }}" data-col-num="{{ col_num }}" data-win-size="{{ win_size }}">
{% for row in range(row_num) %}
<div>
{% for col in range(col_num) %}
<div class="game-cell"
data-coordinate-x="{{ col }}"
data-coordinate-y="{{ row }}"></div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endblock %}
As you can see i have a game-cell class which contains by default 9 elements. I would like to return the data-coordinate-x and data-coordinate-y when I click one of the game-cells. I had a previous try but if I clicked it returned all of the blocks not just the one i clicked on. I have to write it in Js. If you can point me in the right direction that's more than enough for me.
Thanks!
If I understood correctly, you need to access data attributes of your game-cell element. In order to do this, you need to select the element by some ID or class. I have modified your code a little to make it run inside stackoverflow`s platform. I have added an ID which i called "unique" and I also set some values into your coordinate-x and y data attributes. Please review the code bellow and see how I managed to get those data attributes. It's important to notice that this is not the only way to access them.
var gamecell = document.getElementById('unique');
console.log(gamecell.dataset.coordinateX);
console.log(gamecell.dataset.coordinateY);
<nav class="navbar fixed-top navbar-light">
<button id="retry-button" class="btn btn-success">Try again?</button>
Reset settings
</nav>
<div id="game-board" class="mb-3" data-row-num="{{ row_num }}" data-col-num="{{ col_num }}" data-win-size="{{ win_size }}">
<div>
<div class="game-cell" id="unique"
data-coordinate-x="172"
data-coordinate-y="273"></div>
</div>
</div>
Its also possible to get these values using the getAttribute method.
var elem = document.getElementById('unique');
var coordX = elem.getAttribute('data-coordinateX');
var coordY = elem.getAttribute('data-coordinateY');
Please, take a look at this page, it explains some aspects of data attributes:
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes
Simply access your clicked game-cell by: (it will find the clicked coordinateX and coordinateY)
document.querySelectorAll('.game-cell').forEach((game) => {
game.addEventListener('click',function(event){
console.log(game.dataset.coordinateX);
console.log(game.dataset.coordinateY);
});
});
you must to get your element by class name or id(add an id)
than you can get its attributes like this
let gameCell = document.getElementById('game-cell-id');// id for example
gameCell.getAttribute('data-coordinate-x')
I am trying to filter a table by the room name of the records which are in each row. My table rows look like this:
<tr data-room="{{ record.room.room_name|lower|field_name_format}}">
So, when the user checks kitchen, rows related to kitchen shows up in the table and not rows related to other rooms.
And this is the code in the header of my HTML:
{% for room in user_related_rooms %}
document.querySelector('#{{room.room_name|lower|field_name_format}}').addEventListener('change',function (evt) {
updateTableView("{{room.room_name|lower|field_name_format}}", evt.target.checked);
});
{% endfor %}
function updateTableView(room_name, bVisible) {
var dataSelectorVal = "";
switch (room_name)
{
{% for room in user_related_rooms %}
case "{{room.room_name|lower|field_name_format}}":
dataSelectorVal = ".site-table tbody tr[data-room='{{room.room_name|lower|field_name_format}}']";
break;
{% endfor %}
}
$(".site-table tbody tr").has(dataSelectorVal).css('display', bVisible ? "" : "none");
}
Here is the code for the filter:
<!-- Filters -->
<div class="col-md-1">
<h1>Filters</h1>
<form>
<span> by room:</span>
<div class="side-filter-list">
<ul>
{% for room in user_related_rooms %}
<li class="flex-field">
<input type="checkbox" id="cb_{{room.room_name|lower|field_name_format}}" />
<label for="{{room.room_name}}">{{room.room_name}}</label>
</li>
{% endfor %}
</ul>
</div>
</form>
</div>
The browser pauses on the exception. I get error on this line, living_room being the first room in the loop (i.e. the first iteration of the loop):
document.querySelector( '#cb_living_room' ).addEventListener('change', function (evt) {
It seems the above line returns null whereas when I comment out the code and use the console to look for it, it finds it without complaining:
document.querySelector( '#cb_living_room')
Console gives me the output:
<input id="cb_living_room" type="checkbox">
What am I doing wrong? What is going on?
I need to display 10 Song objects at a time with a load more button at bottom that loads 10 more results. This keeps on happening until no more results are available and the load more button is not displayed at that time.
This is what i've come up with
$(document).ready(function () {
$('#song_list div:lt(10)').show();
//var items = ?
//var shown = ?
$('#loadMore').click(function () {
shown = $('#song_list div:visible').size()+10;
if(shown<items) {$('#song_list div:lt('+shown+')').show();}
else {$('#myList li:lt('+items+')').show();
$('#loadMore').hide();
}
});
});
How can I get the values of number of items and number of items shown?
This is the code to display the song list
<div id='song_list'>
{% for song in dj_song_list %}
<div>
<p class="song"><h3>#{{ forloop.counter}} {{ song.name }}</h3></p>
</div>
{% endfor %}
</div>
<button id='loadMore'>Load more</button>
Close the paragraph..."</p>"
<div id='song_list'>
{% for song in dj_song_list %}
<div>
<p class="song"><h3>#{{ forloop.counter}} {{ song.name }]</h3></p>
</div>
{% endfor %}
</div>
<button id='loadMore'>Load more</button>
Try this: http://jsfiddle.net/gebm4/2/
var max_items_page = 2;
$('#song_list div:lt('+max_items_page+')').show();
var shown = null;
var items = $("#song_list").find('div').length;
$('#loadMore').on('click',function(e){
shown = $('#song_list div:visible').length+max_items_page;
if(shown<items) {
$('#song_list div:lt('+shown+')').show();
}else {
$('#myList li:lt('+items+')').show();
$('#loadMore').hide();
}
});