widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #11251
Re: [Merge] lp:~trimardio/widelands-website/scheduling_module into lp:widelands-website
Ok, I added your suggestion Sirver. Now another question what is best:
- create element in js: less hidden element in the basic template
- clone html element in js: more coherent and a bit less work
-let everything as it and remove todo comments: less work, but less coherent
-> I made some diff comments to illustrate where these things are
Another question, should I jquerify all the script for easier understanding by future reader?
Diff comments:
>
> === added file 'media/js/scheduling.js'
> --- media/js/scheduling.js 1970-01-01 00:00:00 +0000
> +++ media/js/scheduling.js 2017-09-29 17:35:23 +0000
> @@ -0,0 +1,313 @@
> +// global variables
> +var lastSelectedDates = []
> +
> +// Create calandar and return it as an object. Useful for callbacks.
> +function createCalandar() {
> + return new Kalendae('calandar', {
> + mode: 'multiple',
> + direction: 'today-future',
> + subscribe: {
> + 'change': function (date) {
> + selectedDate = this.getSelected().split(",");
> + //Cleanup of whitespace
> + for (var i in selectedDate) {
> + selectedDate[i] = selectedDate[i].replace(' ' , '');
> + }
> + dateToUpdate = array_diff(lastSelectedDates, selectedDate);
> + updateAvailableDate(dateToUpdate[0])
> + lastSelectedDates = selectedDate;
> + }
> + }
> + });
> +}
> +
> +//Add warning in case of disparency between system and profil timezone
> +function addTimeZoneWarningIfNeeded() {
> + var userTimeZone = document.getElementById('django-data').getAttribute('user-time-zone')
> + var systemTimeZone = - new Date().getTimezoneOffset()/60
> + if ( systemTimeZone != userTimeZone) {
> + document.getElementById('timezone-error').removeAttribute("hidden");
> + profilTime = document.getElementsByClassName('profil-time');
> + for (var element in profilTime) {
> + profilTime[element].innerHTML = cleanAndAddSign(userTimeZone);
> + }
> + document.getElementById('system-time').innerHTML = cleanAndAddSign(systemTimeZone);
> + }
> +}
> +
> +function addPreviousDateFromUser(calendar) {
> + //Populate the current date with already filled date by the user
> + old_availabilities_string_JSON = document.getElementById('django-data').getAttribute('day-to-fill')
> + old_availabilities_list = stringJSONtoJSList(old_availabilities_string_JSON)
> + if (old_availabilities_list == "") {
> + return;
> + }
> + dateToAdd = []
> + for (var date in old_availabilities_list) {
> + // Extract day of the date. See format in view.py.
> + dateString = old_availabilities_list[date].substring(1,11);
> + if (!existInList(dateToAdd, dateString)){
> + dateToAdd.push(dateString)
> + }
> + }
> + dateStringList = dateToAdd.join(',')
> + calendar.setSelected(dateStringList);
> + for (var date in old_availabilities_list) {
> + // Extract hour of the date. See format in view.py.
> + hourString = old_availabilities_list[date].substring(12,14);
> + // Extract day of the date. See format in view.py.
> + dateString = old_availabilities_list[date].substring(1,11);
> + hourString = removeZeroIfUnderTen(hourString);
> + displayHourForDate(dateString, hourString);
> + }
> +}
> +
> +function addOtherUsersAvailabilities() {
> + //Populate the result area showing other users and their disponibilities
> + if (document.getElementById('django-data').getAttribute('users-to-fill')) {
> + var otherPlayerAvailabilitiesJSON = document.getElementById('django-data').getAttribute('users-to-fill');
> + otherPlayerAvailabilities = JSON.parse(otherPlayerAvailabilitiesJSON)
> + }
> + noOtherUser = true;
> + for (var user in otherPlayerAvailabilities) {
> + noOtherUser = false;
> + dateList = otherPlayerAvailabilities[user]
> + for (var date in dateList) {
> + createUserDivOrUpdateIt(user, dateList[date])
> + }
> + }
> + if (noOtherUser) {
> + document.getElementById('no-user-to-display').removeAttribute("hidden");
> + }
> +}
> +
> +function sendDataAsForm(calendar) {
> + //Get informations from selected hours
> + var selectedDates = calendar.getSelected().split(",");
> + var selectedDatesList = [];
> + for (var d in selectedDates) {
> + //remove whitespace
> + selectedDates[d] = selectedDates[d].replace(" ", "");
> + var dateID = 'day-' + selectedDates[d];
> + dateObj = document.getElementById(dateID);
> + if (dateObj) {
> + hoursList = dateObj.getElementsByClassName('hours');
> + selectedHours = dateObj.getElementsByClassName('selected');
> + if (selectedHours[0]){
> + for (var h in hoursList) {
> + if (hasClass(hoursList[h] , 'selected')){
> + var hourAsDate = new Date(selectedDates[d] + "T" + addZeroIfUnderTen(h) + ":00:00")
> + // we get the hour in utc time and remove unneeded informations
> + stringDate = hourAsDate.toISOString().slice(0,13)
> + selectedDatesList.push(stringDate);
> + }
> + }
> + }
> + }
> + }
> + //Send informations to server
> + post('.', selectedDatesList)
> +}
> +
> +//Add or remove available dates in the ui.
> +function updateAvailableDate(date) {
> + newDateID = "day-" + date
> + dateAlreadyExist = !!document.getElementById(newDateID);
> + document.getElementById('second-step').removeAttribute('hidden');
> + if (dateAlreadyExist) {
> + document.getElementById(newDateID).remove();
> + } else {
> + var original = document.getElementById('day-template');
> + // We clone the date and fix different attributes
> + var newDate = original.cloneNode(true);
> + newDate.id = "day-" + date;
> + newDate.removeAttribute("hidden");
> + var textDate = new Date(date);
> + textDate = textDate.toDateString();
> + newDate.getElementsByClassName('day-title')[0].innerHTML = '<h3>' + textDate + '</h3>';
> + //We add the listeners to each hours One for the click event, the other for the hover when the mouse is pressed
> + hoursObj = newDate.getElementsByClassName('hours');
> + for (var i = 0; i < hoursObj.length; i++) {
> + hoursObj[i].addEventListener('click', updateHour, false);
> + hoursObj[i].addEventListener("mouseover", function(e){
> + if(e.buttons == 1 || e.buttons == 3){
> + updateHour(e);
> + }
> + })
> + }
> + //we look for the order the new date should be in
> + daysList = document.getElementById('days-wrapper').getElementsByClassName('days');
> + //We finally add the new date
> + document.getElementById('days-wrapper').appendChild(newDate);
> + }
> +
> +}
> +
> +function updateHour (event) {
> + var div = (event.fromElement ? event.fromElement : event.currentTarget);
> + isAlreadySelected = hasClass(div, 'selected');
> + if (isAlreadySelected) {
> + div.className = 'hours';
> + } else {
> + div.className += ' selected';
> + }
> +}
> +
> +function displayHourForDate(date, hour, user) {
> + var dateDivID = 'day-' + date
> + if (user) {
> + dateDivID = user + '-day-' + date
> + }
> + dateDiv = document.getElementById(dateDivID);
> + hourDiv = dateDiv.getElementsByClassName('hours');
> + for (var hourInDiv in hourDiv) {
> + if (hourInDiv == hour) {
> + hourDiv[hourInDiv].className += ' selected';
> + }
> + }
> +}
> +
> +function createUserDivOrUpdateIt(user, availTime) {
> + if (!document.getElementById("user-" + user)){
> + var original = document.getElementById('other-user-template');
> + // We clone the date and fix different attributes
> + var otherUser = original.cloneNode(true);
> + otherUser.id = "user-" + user;
> + otherUser.removeAttribute("hidden");
> + var jsEventHTML = "/messages/compose/" + user
Should I rather make clones of html elements?
> + var imageHTML = '<img src="/wlmedia/forum/img/send_pm.png" alt="" class="middle"><span class="middle">Send PM</span>'
> + var userTitle = otherUser.children[0]
> + var button = document.createElement("button");
> + button.innerHTML = imageHTML;
> + button.onclick = function(){
> + window.location.href = '/messages/compose/' + user;
> + }
> + var usernameP = document.createElement('p')
> + usernameP.innerHTML = user;
> + userTitle.appendChild(usernameP)
> + userTitle.appendChild(button)
> + } else {
> + otherUser = document.getElementById("user-" + user);
> + }
> + var dtavailTime = new Date(availTime + ":00:00");
> + //Remove timezone offset which js automatically add...
> + js_offset = dtavailTime.getTimezoneOffset()/60
> + dtavailTime = dtavailTime.addHours(js_offset);
> + textDate = dtavailTime.toDateString();
> + var dateFormated = dtavailTime.getFullYear() + "-" + dtavailTime.getMonth() + '-' + dtavailTime.getDay()
> + var availTimeFormated = dtavailTime.getHours()
> + var originalDay = document.getElementById('other-day-template')
> + if (!document.getElementById(user + "-day-" + dateFormated)) {
> + var day = originalDay.cloneNode(true);
> + day.id = user + "-day-" + dateFormated;
> + day.removeAttribute("hidden");
> + day.getElementsByClassName('day-title')[0].innerHTML = '<h3>' + textDate + '</h3>';
> + otherUser.appendChild(day);
> + }
> + document.getElementById('other-users-wrapper').appendChild(otherUser);
> + displayHourForDate(dateFormated, availTimeFormated, user);
> +}
> +
> +/*****************************/
> +/********* utilities *********/
> +/*****************************/
> +// read as "Stackoverflow coded this"
> +
> +//Return diff between two list
> +function array_diff(a1, a2) {
> + var a = [], diff=[];
> + for (var i = 0; i < a1.length; i++) {
> + a[a1[i]] = true;
> + }
> + for (var i=0; i < a2.length; i++) {
> + if (a[a2[i]]) {
> + delete a[a2[i]];
> + } else {
> + a[a2[i]] = true;
> + }
> + }
> + for (var k in a) {
> + diff.push(k)
> + }
> + return diff
> +}
> +
> +function hasClass(element, cls) {
> + return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
> +}
> +
> +//We need a custom function to submit a form because our data isn't formated as a form.
> +function post(path, params, method) {
> + method = method || "post"; // Set method to post by default if not specified.
> + // The rest of this code assumes you are not using a library.
> + // It can be made less wordy if you use one.
> + var form = document.createElement("form");
> + form.setAttribute("method", method);
> + form.setAttribute("action", path);
> + for(var key in params) {
> + var hiddenField = document.createElement("input");
> + hiddenField.setAttribute("type", "hidden");
> + hiddenField.setAttribute("name", key);
> + hiddenField.setAttribute("value", params[key]);
> +
> + form.appendChild(hiddenField);
> + }
> + //CSRF token
> + var csrf_div = document.createElement("div");
> + csrf_div.innerHTML = document.getElementById('django-data').getAttribute('csrf-token')
> + form.appendChild(csrf_div);
> + document.body.appendChild(form);
> + form.submit();
> +}
> +
> +function cleanJSONfromWhiteSpace(json) {
> + var name, newName;
> + for (var name in json) {
> + // Get the name without spaces
> + newName = name.replace(/ /g, "");
> + // If that's different...
> + if (newName != name) {
> + // Create the new property
> + json[newName] = json[name];
> + // Delete the old one
> + delete json[name];
> + }
> + }
> + return json;
> +}
> +
> +function stringJSONtoJSList(json) {
> + //removes brackets
> + json = json.substring(1, json.length-1);
> + var jsonList= json.split(",")
> + for (var i in jsonList){
> + jsonList[i] = jsonList[i].replace(/\s/g, '');
> + }
> + return jsonList
> +
> +}
> +
> +function addZeroIfUnderTen(number) {
> + return ('0' + number).slice(-2)
> +}
> +
> +function removeZeroIfUnderTen(number) {
> + return parseInt(number, 10);
> +}
> +
> +Date.prototype.addHours = function(h) {
> + this.setTime(this.getTime() + (h*60*60*1000));
> + return this;
> +}
> +
> +function existInList(list, value) {
> + return list.indexOf(value) > -1
> +}
> +
> +function cleanAndAddSign(number) {
> + if (number < 0) {
> + return ' ' + parseInt(number)
> + } else {
> + return '+ ' + parseInt(number)
> + }
> +}
> \ No newline at end of file
>
> === added file 'templates/wlscheduling/find.html'
> --- templates/wlscheduling/find.html 1970-01-01 00:00:00 +0000
> +++ templates/wlscheduling/find.html 2017-09-29 17:35:23 +0000
> @@ -0,0 +1,47 @@
> +
> +
> +{% extends "wlscheduling/base.html" %}
> +{% comment %}
> + vim:ft=htmldjango
> +{% endcomment %}
> +
> +{% block content %}
> +<script type="text/javascript">
> +document.addEventListener('DOMContentLoaded', function(){
> + addTimeZoneWarningIfNeeded();
> + addOtherUsersAvailabilities();
> +}, false);
> +</script>
> +
> +<div class="blogEntry">
> + <h1>Times other players are available</h1>
> + <h3 id="timezone-msg">You are currently noted as UTC <span class="profil-time"></span></h3>
> + <div id="timezone-error" class="errormessage" hidden="hidden">WARNING! The time indicated by your system (UTC <span id="system-time"></span>) is different from the one stored in your profile (UTC <span id="profil-time"></span>). By default we will use the one stored in your profile.<br /> <a href="{% url 'profile_edit' %}">Edit Profile</a></div>
> + <div id="other-users-wrapper"></div>
> + <div id="no-user-to-display" hidden="hidden">Sorry currently there isn't anybody who has scheduled a gaming session. This shouldn't happen. Who doesn't want to play to widelands????!! :O :O</div>
> +
> +</div>
> +
> +<!-- TODO entirely in JS? -->
Should those elements be create entirely in js?
> +<div id="other-day-template" hidden="hidden">
> + <div class="day-title"></div>
> + <div id="hours-wrapper" class="hours-wrapper" >
> + {% for i in "xxxxxxxxxxxxxxxxxxxxxxxx" %}
> + <div class="hours" title="{{ forloop.counter0 }} to {{ forloop.counter0|add:1 }} hour"></div>
> + {% endfor %}
> + </div>
> +</div>
> +
> +
> +<!-- TODO remove this template and do it entirely in js (it doesn't need any django value) -->
> +<div id="other-user-template" class="other-user-div" hidden="hidden">
> + <div class="title"></div>
> +</div>
> +
> +
> +
> +<!-- Div to send django data to js file -->
> +<div id="django-data" user-time-zone="{{user.wlprofile.time_zone}}" users-to-fill="{{other_users_availabilities}}"></div>
> +
> +
> +{% endblock %}
> \ No newline at end of file
>
> === added file 'templates/wlscheduling/scheduling.html'
> --- templates/wlscheduling/scheduling.html 1970-01-01 00:00:00 +0000
> +++ templates/wlscheduling/scheduling.html 2017-09-29 17:35:23 +0000
> @@ -0,0 +1,81 @@
> +
> +{% extends "wlscheduling/base.html" %}
> +{% comment %}
> + vim:ft=htmldjango
> +{% endcomment %}
> +
> +
> +
> +{% block content %}
> +<script type="text/javascript">
> +document.addEventListener('DOMContentLoaded', function(){
> + var calendar = createCalandar();
> + addTimeZoneWarningIfNeeded();
> + addPreviousDateFromUser(calendar);
> + addOtherUsersAvailabilities();
> +
> + //Validate btn
> + document.getElementById('validate-btn').onclick = function () {
> + sendDataAsForm(calendar);
> + }
> +}, false);
> +</script>
> +
> +<h1>Multiplayer</h1>
> +
> +<div class="blogEntry">
> + <h2>Select the dates you'll be available on</h2>
> + <h3 id="timezone-msg">You are currently noted as UTC <span class="profil-time"></span></h3>
> + <div id="timezone-error" class="errormessage" hidden="hidden">WARNING! The time indicated by your system (UTC <span id="system-time"></span>) is different from the one stored in your profile (UTC <span class="profil-time"></span>). By default we will use the one stored in your profile.<br /> <a href="{% url 'profile_edit' %}">Edit Profile</a></div>
> + <div id="calandar"></div>
> +
> + <div id="second-step" hidden="hidden">
> + <h2>Select the hours you'll be available on these dates</h2>
> + <div id="days-wrapper"></div>
> + <h2>Players that are currently available at the same hours as you</h2>
> + <div id="other-users-wrapper"></div>
> + <div id="no-user-to-display" hidden="hidden">Sorry, there are currently no players available at these hours. But your availabilities are noted, and another user might want to play with you!</div>
> +
> +
> + <button id="validate-btn">Update</button>
> + </div>
> +</div>
> +
> +<!-- Templates for the js script -->
> +<!-- TODO entirely in JS? -->
Should those elements be create entirely in js?
> +<div id="day-template" class="day" hidden="hidden">
> + <div class="day-title"></div>
> + <div class="hours-title-wrapper">
> + {% for i in "xxxxxxxxxxxxxxxxxxxxxxxxx" %}
> + <p>{{ forloop.counter0 }}</p>
> + {% endfor %}
> + </div>
> + <div class="hours-wrapper">
> + {% for i in "xxxxxxxxxxxxxxxxxxxxxxxx" %}
> + <div class="hours"></div>
> + {% endfor %}
> + <div class="hidden-hour"></div>
> + </div>
> +</div>
> +
> +<!-- TODO entirely in JS? -->
> +<div id="other-day-template" hidden="hidden">
> + <div class="day-title"></div>
> + <div id="hours-wrapper" class="hours-wrapper" >
> + {% for i in "xxxxxxxxxxxxxxxxxxxxxxxx" %}
> + <div class="hours" title="{{ forloop.counter0 }} to {{ forloop.counter0|add:1 }} hour"></div>
> + {% endfor %}
> + </div>
> +</div>
> +
> +
> +<!-- TODO remove this template and do it entirely in js (it doesn't need any django value) -->
> +<div id="other-user-template" class="other-user-div" hidden="hidden">
> + <div class="title"></div>
> +</div>
> +
> +<!-- Div to send django data to js file -->
> +<div id="django-data" user-time-zone="{{user.wlprofile.time_zone}}" day-to-fill = "{{ current_user_availabilities }}" users-to-fill="{{other_users_availabilities}}" csrf-token = "{% csrf_token %}"></div>
> +
> +
> +{% endblock %}
--
https://code.launchpad.net/~trimardio/widelands-website/scheduling_module/+merge/331477
Your team Widelands Developers is subscribed to branch lp:widelands-website.
References