xref: /plugin/kanban/script.js (revision f4b18c92ed322afef4847ac5c154503a8bb2d449)
1jQuery(function() {
2    var $board = jQuery('.kanban-board');
3	var $mycard = jQuery('.kanban-card');
4    if (!$board.length) return;
5    var boardName = $board.data('board');
6
7    // Helper to send data to PHP
8    function saveCardData($card) {
9        jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', {
10            call: 'kanban_save', // Match this with your action.php check
11            board: boardName,
12            card_id: $card.data('id'),
13            column: $card.closest('.kanban-col').data('id'),
14            name: $card.find('.card-title').text(),
15            importance: $card.attr('class').split(' ').filter(c => ['high','medium','low'].includes(c))[0] || 'medium',
16            desc: $card.find('.card-desc').text(),
17			note: $card.find('.card-note').text(),
18			checked: $card.find('.checkbox-inline').prop('checked')
19        }).done(function(res){ console.log("Saved:", res); });
20    }
21
22	// Prevent movement of the card column placeholder
23	/*
24	jQuery(function() {
25    jQuery(".cards-container").sortable({
26        // Only allow children WITHOUT the 'fixed-top-item' class to be moved
27        items: "> div:not(.fixed-top)",
28
29        // Listen for when an item is being moved to a new position
30        update: function(event, ui) {
31            // ui.item.index() returns the current position in the DOM
32            if (ui.item.index() === 0) {
33                // Find the fixed element
34                var $fixed = jQuery(this).find(".fixed-top");
35                // Immediately force the dropped item to go AFTER the fixed div
36                ui.item.insertAfter($fixed);
37            }
38        }
39		});
40	});
41	*/
42
43    // Initialize Drag and Drop ONCE
44
45    jQuery(".cards-container").sortable({
46        connectWith: ".cards-container",
47        placeholder: "ui-sortable-placeholder",
48        tolerance: "pointer",
49
50
51        start: function(e, ui) {
52		//start-added
53		const card = document.querySelector('.kanban-card');
54
55		distance: 15, // Dragging won't trigger until moved 15px
56        // Add and start the draggable class only AFTER the 15px threshold is met
57		ui.item.addClass("is-dragging");
58		//distance: -15, // Dragging won't trigger until moved -15px
59        // Add and start the draggable class only AFTER the -15px threshold is met
60		//ui.item.addClass("is-left-dragging");
61		//end-added
62            ui.placeholder.height(ui.item.outerHeight());
63        },
64        stop: function(event, ui) {
65			//Remove the draggable class when you are done
66			ui.item.removeClass("is-dragging");
67			//ui.item.removeClass("is-left-dragging");
68            //Fires once when dropped
69            //alert(ui.item.text()); //debugging function works
70			//alert(ui.item.data('id')); //debugging function
71			//saveCardData(ui.item);
72			//Modified to capture the text value in JQuery format
73			//saveCardData(ui.item);
74			saveCardData(ui.item); //replaced to bring about real name for saving
75			//const divId = ui.item.closest('.kanban-col').data('id');
76			//ui.item.closest('.kanban-col').preventDefault(); // This is required to allow a drop
77			//console.log("Dropped on ID:", divId);
78        }
79    }).disableSelection();
80
81    // Fix: Event Delegation for "Add Card"
82    $board.on('click', '.add-card-btn', function() {
83        var name = prompt("Job Name:");
84        if (!name) return;
85        var imp = (prompt("Importance (high, medium, low):", "medium") || "medium").toLowerCase();
86        var cardId = "c" + Date.now();
87		var note = "There are no notes on this card yet.";
88
89        var $newCard = jQuery(`
90            <div class="kanban-card ${imp}" data-id="${cardId}">
91				<input type="checkbox">
92                <strong class="card-title">${name}</strong>
93                <div class="card-desc">Click to add description...</div>
94				<div style="color:black;">Refresh for Notes</div>
95				<div class="card-note"></div>
96            </div>
97        `);
98
99        jQuery(this).closest('.kanban-col').find('.cards-container').append($newCard);
100        saveCardData($newCard);
101    });
102
103	//make the kanban cards add note button clickable
104	$mycard.on('click', '.btn-notes', function() {
105		//var $note = jQuery(this);
106		//var currentNote = $note.text();
107		//alert('this is my click');
108		var mynote = prompt("Add Note:","");
109		//Get the current username
110		//var userlogin = JSINFO['user']; // Login username
111		// Standard DokuWiki configuration object
112		//attempt to query the user from the interface first
113		var userlogin = jQuery('meta[name="plugin_do_user"]').attr('content');
114		//console.log(JSINFO); //debugging line
115		if (!userlogin && typeof JSINFO !== 'undefined') {
116			//pull the user from php if the interface query fails
117			userlogin = JSINFO['plugin_do_user'];
118		}
119		//return currentNote + " | " + note;
120		if(mynote !== null){
121			//Sanitize the input
122			function sanitizeInlineCommands(inputText) {
123				// Regex to match "javascript:" and other common inline command patterns
124					const commandPattern = /javascript:|on\w+=|style="[^"]*expression[^"]*"|\+/gi;
125
126					// Replace found commands with an empty string
127					return inputText.replace(commandPattern, '');
128			}
129
130			// Example usage
131			//const userInput = 'Hello <a href="javascript:alert(1)">Click</a>! <img src=x onerror=alert(1)>';
132			const cleanedNote = sanitizeInlineCommands(mynote);
133			//end sanitize
134			//Get the current date string
135			const date = new Date().toLocaleDateString('en-US');
136			//Get the current time string
137			const mytime = new Date().toLocaleTimeString();
138			//Get the closest kanban-card to the object clicked
139			var $note = jQuery(this).closest('.kanban-card');
140			// filter() checks if $note IS the class; find() checks if it's INSIDE $note
141			var $target = $note.filter('.card-note').add($note.find('.card-note'));
142			// 2. Attach new data to the inner div with <br> delimiter
143			$target.append("<br>+ " + userlogin + " - " + date + ":" + mytime + " - " + cleanedNote);
144
145			saveCardData($note.closest('.kanban-card'));
146		}
147	});
148
149    // Fix: Event Delegation for Clickable Description
150    $board.on('click', '.card-desc', function() {
151        var $desc = jQuery(this);
152        var currentText = $desc.text() === "Click to add description..." ? "" : $desc.text();
153        var newDesc = prompt("Enter Description:", currentText);
154        if (newDesc !== null) {
155            $desc.text(newDesc || "Click to add description...");
156            saveCardData($desc.closest('.kanban-card'));
157        }
158    });
159    // Fix: Event Delegation for Clickable Checkbox
160    $board.on('click', '.checkbox-inline', function() {
161        var $checkit = jQuery(this);
162        var currentVal = $checkit.prop('checked');
163        if ($checkit){
164            saveCardData($checkit.closest('.kanban-card'));
165        }
166    });
167
168
169});
170