Greasy Fork is available in English.

منظم جدول الجامعة الاسلامية

اضافة لتعديل مظهر الجدول بالجامعة الاسلامية الى جدول مرتب تبعا لايام الاسبوع بضغطة زر

Fra og med 28.08.2022. Se den nyeste version.

// ==UserScript==
// @name منظم جدول الجامعة الاسلامية
// @description اضافة لتعديل مظهر الجدول بالجامعة الاسلامية الى جدول مرتب تبعا لايام الاسبوع بضغطة زر
// @name:en IU Table Organizer
// @description:en A script to order the lectures table according to weekdays on the Islamic University website
// @include https://eduportal.iu.edu.sa/iu/ui/student/homeIndex.faces
// @include https://eduportal.iu.edu.sa/iu/ui/student/*/*/*
// @include http://eduportal.iu.edu.sa/iu/ui/student/*
// @include https://eduportal.iu.edu.sa/iu/ui/student/student_schedule/index/studentScheduleIndex.faces
// @version 1.2.7
// @icon https://www.google.com/s2/favicons?domain=sso.iu.edu.sa
// @namespace https://greasyfork.org/users/814159
// @icon https://icons.iconarchive.com/icons/fatcow/farm-fresh/32/table-icon.png
// @license Mozilla Public License 2.0 
// ==/UserScript==


// Rows are within these 2 class elements
row1 = document.querySelectorAll(".ROW1");
row2 = document.querySelectorAll(".ROW2");
// Where we append the info of every row
let rows = [];
const originalTableNode = document.getElementById('scheduleFrm:studScheduleTable');
const days = ['الاحد','الاثنين','الثلاثاء','الاربعاء','الخميس'];
let newTable = {};
let newTableNode;
let on = false;
// This feature is not used yet
// The colors that will be used for each subject
let colors = ["Blue", "Black", "Crimson", "Green", "Grey", "OrangeRed", "Purple", "Red", "SpringGreen", "MediumTurquoise", "Navy", "GoldenRod"];
let subject_colors = {};
// Increases when a color is assigned to a subject
let color_index = 0;

// Recursive function that takes a node and returns the deepest text in that node
// By repetitively going into the first child of an element until an end road was found
function endText(node) {
    if (!node.firstElementChild) {
        return node.innerHTML;
    } else {
        return endText(node.firstElementChild);
    }
}

// Gathers the all the lectures and subjects info in an array called rows
function getTableInfo(nodes) {
    // For every row in 'nodes' elements
    for (let i = 0; i < nodes.length; i++) {
        // initialize an object for a row
        let row_obj = {};
        // Choose one element with class ROW1
        let row = nodes[i];
        let cells = row.children;
    
        // For every cell in the row
        for (let j = 0; j < cells.length; j++) {
            try {
                // If the cell is the messy one with 3 values at the same time
                if (cells[j].dataset.th.includes("القاعة")) {
                    // Get the names of the cells by splitting the string
                    let headers = cells[j].dataset.th.split(/\s+/);
                    // May look stupid but it's the best way to get the elements representing the lectures
                    let lectures = cells[j].firstElementChild.firstElementChild.children;
                    row_obj["محاضرات"] = [];
    
                    // For each lecture element
                    for (let k = 0; k < lectures.length; k++) {
                        let data = {};
                        // For every header representing values
                        for (let l = 0; l < headers.length; l++) {
                            let currentHeader = headers[l];
                            // add the header with its value in the lecture (depends on the data being consistent)
                            data[currentHeader] = endText(lectures[k].children[l]).trim();
                            // If the text has '&nbsp' which means it's the messy 'day' cell 
                            // then split it and get the part that has the number
                            if (data[currentHeader].includes("&nbsp")) {
                                data[currentHeader] = data[currentHeader].split('; ')[1].trim().split(' ');
                            }
                        }
                        // Apeend the object with lectures data to 'lectures' key in row_obj
                        row_obj["محاضرات"].push(data);
                    }
                } else {
                    // Else get the deepest text and give it to the name in the dataset th
                    let cellName = cells[j].dataset.th.trim();
                    row_obj[cellName] = endText(cells[j]).trim();
                    if (row_obj[cellName].includes("&nbsp")) {
                        row_obj[cellName] = row_obj[cellName].split('&')[0].trim();
                    }
                }
            } catch(err) {
                console.log(err)
            }
        }
        rows.push(row_obj);
    }    
}

// The part where everything about the original schedule is formatted and stored
try {
    // Make a button to activate the table or deactivate it
    let button = document.createElement('span');
    let cell = document.createElement('td');
    button.classList.add("BUTTON_LINK");
    button.style.cursor = "pointer";
    // The saving button
    let save = document.createElement('span');
    save.style.cursor = "pointer";
    save.innerHTML = `<i class="fa fa-save" style="color: Black; font-size: 20px;"></i>`;
    let save_td = document.createElement('td');

    // Remember the last choice
    if (on) {
        button.style.backgroundColor = "firebrick";
        button.innerHTML = "الجدول&nbspالاصلي";
        originalTableNode.style.display = 'none';
        save.style.display = null;

        if (newTableNode) {
            newTableNode.style.display = null;
        } else {
            getTableInfo(row1);
            getTableInfo(row2);
            // console.log(rows);
            getNewTable();
            appendTable();
        }
    } else {
        // button.style.backgroundColor = "rgb(1, 130, 165)";
        button.innerHTML = "نظم&nbspالجدول";
        save.style.display = 'none';
        if (newTableNode){
            newTableNode.style.display = 'none';
        }
    }

    // Append the button to the DOM
    cell.appendChild(button);
    save_td.appendChild(save);
    document.getElementById("scheduleFrm:printLink").parentElement.parentElement.appendChild(cell);
    document.getElementById("scheduleFrm:printLink").parentElement.parentElement.appendChild(save_td);

    button.onclick = function() {
        if (on) {
            on = false;
            button.style.backgroundColor = null;
            button.innerHTML = "نظم&nbspالجدول";
            save.style.display = 'none';
            originalTableNode.style.display = null;
            newTableNode.style.display = 'none';
        } else {
            on = true;
            button.style.backgroundColor = "firebrick";
            button.innerHTML = "الجدول&nbspالاصلي";
            save.style.display = null;
            // Hide the original table
            originalTableNode.style.display = 'none';
            if (newTableNode) {
                newTableNode.style.display = null;
            } else {
                if (rows.length == 0) {
                    getTableInfo(row1);
                    getTableInfo(row2);
                }
                getNewTable();
                appendTable();
            }
        }
    }

    // Printing the schedule
    function Popup(data)
    {
        var mywindow = window.open('', 'my div', 'height=800,width=1200');
        mywindow.document.write('<html><head><title></title>');
        /*optional stylesheet*/ //mywindow.document.write('<link rel="stylesheet" href="main.css" type="text/css" />');
        mywindow.document.write('</head><body style="direction:rtl;"><pre>');
        mywindow.document.write(data);
        mywindow.document.write('</pre></body></html>');
        mywindow.document.close();
        mywindow.print();
        return true;
    }

    save.onclick = function() {
        let wrap = document.createElement('div');
        wrap.appendChild(newTableNode.cloneNode(true));
        Popup(wrap.innerHTML);
    }
} catch(err) {
    console.log(err);
}

function getNewTable()
{
    try {
        // Populate the new table with the days and their lectures
        for (i in days) {
            newTable[days[i]] = [];
        }
        for (i in rows) {
            let subjectLectures = rows[i]['محاضرات'];
            for (j in subjectLectures) {
                let lecture = subjectLectures[j];
                let time = lecture['الوقت'];

                function value(t) {
                    // Give a numerical value for the time of the day the lecture is at
                    let hour = parseInt(t.slice(0, 2), 10);
                    let minutes = parseInt(t.slice(3, 5), 10);
                    let total = (hour * 60) + minutes;

                    if (t.slice(0, 10).includes('م') && hour != 12) {
                        total += 720;
                    }

                    return total;
                }

                for (k in lecture["اليوم"]) {
                    let day = days[parseInt(lecture["اليوم"][k])-1];
                    newTable[day].push({subject: rows[i]['اسم المقرر'], activity: rows[i]['النشاط'], 
                    time: time, place: lecture['القاعة'], value: value(time)});

                    // Assigining a color to each subject
                    if (!(rows[i]['اسم المقرر'] in subject_colors)){
                        subject_colors[rows[i]['اسم المقرر']] = colors[color_index];
                        color_index++;
                    }
                }
            }
        }

        // Sort the lectures according to their time values
        for (i in newTable) {
            newTable[i].sort(function(a, b) {
                return a.value - b.value;
              });
        }

        function insert_after(element, array, index){
            let new_array = [];
            for (i = 0; i < array.length; i++) {
                if (i == index+1) {
                    new_array.push(element);
                }
                new_array.push(array[i]);
            }
            return new_array;
        }

        // Add the breaks between lectures
        for (d = 0; d < days.length; d++) {
            // New deep copy for day lectures
            let edited_day = JSON.parse(JSON.stringify(newTable[days[d]]));
            let uni_day = newTable[days[d]];
            // Skip value is how many indexes to skip due to previously added breaks
            let skip = 0;
            //console.log("lectures of a day",uni_day, uni_day.length);
            for (l = 0; l < uni_day.length - 1; l++) {
                let difference = uni_day[l+1].value - uni_day[l].value;
                console.log(`the difference between ${uni_day[l+1].subject} and ${uni_day[l].subject}`, difference);
                if (difference > 60) {
                    let break_obj = {subject: null, activity: "break", time: null, place: null, value: difference - 60};
                    edited_day = insert_after(break_obj, edited_day, l+skip);
                    skip++;
                }
            }
            newTable[days[d]] = edited_day;
        }
        console.log(newTable);
        console.log(subject_colors);
        // console.log(newTable);
    } catch(err) {
        console.log(err);
    }
}


// Append the new table info to the DOM
function appendTable() {
    // Creating the table with its attributes and children
    let table = document.createElement('table');
    table.classList.add('rowFlow');
    table.width = "100%";
    table.cellPadding = '0';
    table.cellPadding = '0';
    table.border = '1';
    originalTableNode.insertAdjacentElement('afterend', table);

    let thead = document.createElement('thead');
    let tbody = document.createElement('tbody')
    table.appendChild(thead);
    table.appendChild(tbody);

    // Append days as table headers
    for(i in days) {
        let th = document.createElement('th');
        th.innerHTML = days[i];
        th.classList.add('HEADING');
        th.scope = "col";
        thead.appendChild(th);
    }

    function maxDayLength(obj) {
        // Returns the highest number of lictures in one day
        let max;
        for (i in obj) {
            if (obj[i].length > max) {
                max = obj[i].length;
            } else if (!max) {
                max = obj[i].length;
            } else {
                continue
            }
        }
        return max;
    }

    const maxLength = maxDayLength(newTable);

    // append empty cells as many as the number of lectures during the busiest day
    for (let i = 0; i < maxLength; i++) {
        let tr = document.createElement('tr');
        tbody.appendChild(tr);
        for (j in days) {
            let td = document.createElement('td');
            tr.appendChild(td);
        }
    }

    // trs are table rows
    let trs = tbody.children;
    for (i in days) {
        // For each day of the weekdays get the info of that day
        let currentDay = newTable[days[i]];
        
        // For each lecture in that day
        for (j in currentDay) {
            // Add it as a break if it is
            if (currentDay[j].activity == "break") {
                let hrs = currentDay[j].value/60;
                let text;
                let color = "Grey";
                if (hrs > 10){
                    trs[j].children[i].innerHTML = `<strong style="color:${color}">&nbsp;&nbsp;&nbsp;&nbsp;${currentDay[j].value/60} ساعة راحة</strong>`;
                } else if (hrs > 2) {
                    trs[j].children[i].innerHTML = `<strong style="color:${color}">&nbsp;&nbsp;&nbsp;&nbsp;${currentDay[j].value/60} ساعات راحة</strong>`;
                } else if (hrs == 2) {
                    trs[j].children[i].innerHTML = `<strong style="color:${color}">&nbsp;&nbsp;&nbsp;&nbsp;ساعتين راحة</strong>`;
                } else if (hrs == 1) {
                    trs[j].children[i].innerHTML = `<strong style="color:${color}">&nbsp;&nbsp;&nbsp;&nbsp;ساعة راحة</strong>`;
                }
                continue;
            }
            // Insert the info in the following way
            trs[j].children[i].innerHTML = `<strong style="color:Black">${currentDay[j].subject}</strong> ${currentDay[j].activity}<br>
                                            ${currentDay[j].time}<br>
                                            القاعة: ${currentDay[j].place}`;
        }
    }
    // To make this new node global
    newTableNode = table;
}