Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
code-master-ajay committed Feb 20, 2024
2 parents a4b89a4 + 3ac3e8f commit baf12e0
Show file tree
Hide file tree
Showing 8 changed files with 637 additions and 1 deletion.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
Texty : A Live text editor for friends.
## **Texty** : A Live text editor for friends.

### You can find a demo at [Texty](https://bot2x.github.io/Texty/)


> [!NOTE]
> The project is actively being developed. It is experimental at the moment.
27 changes: 27 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,31 @@
})
</script>
</body>
<html>
<head>
<title>Texty</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- <div id="editor">
This is where the editor will live and evolve.
</div> -->

<div style="display: flex; height: 100%;">
<div id="top-container-1" class="top_container"></div>
<div id="top-container-2" class="top_container"></div>
</div>

<script type="text/javascript" src="js/layoutcontrols/layoutprovide.js"></script>
<script type="text/javascript" src="js/layoutcontrols/tabControls.js"></script>
<script type="text/javascript" src="js/utils/tabFunctions.js"></script>
<script>

tp = TabLayoutProvider();
const layout1ID = tp.createLayout(document.getElementById("top-container-1"), nTabs=3);
const layout2ID = tp.createLayout(document.getElementById("top-container-2"), nTabs=4);

</script>
</body>
</html>
54 changes: 54 additions & 0 deletions js/layoutcontrols/layoutprovide.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

//This will will used to manage instances of tab layouts being demanded.
function TabLayoutProvider () {
let numTabLayouts = 0; //Hold the number of layouts provided.

let providedLayouts = {};

//get an instance of TabController.

function createLayout(containerRef, nTabs=0) {
if (!containerRef) {
alert("[Undefined Reference] Cannot create a tab layout without the container reference.");
return;
}
const tabController = TabController(nTabs, numTabLayouts);

const tabEditor = tabController.initTabLayout(containerRef);
// console.log(tabEditor);

console.log("tab controller ref : ", tabController);

tabController.doHydrate(tabEditor, tabController);

//Select the first tab as a default behavior.
tabEditor.linkContainer.firstElementChild.click();

tabLayoutAddedAt(containerRef, tabController);

return tabController.getMyTabLayoutId();
}

function tabLayoutAddedAt (containerRef, tabControllerRef) {
//Keep a ref around and increment.
providedLayouts[numTabLayouts] = {
"containerRef" : containerRef,
"tabControllerRef" : tabControllerRef,
}
numTabLayouts++;
}

function getSelectedTabAtLayout (tablayoutid) {
if (Number.isInteger(tablayoutid) && tablayoutid <= numTabLayouts) {
return providedLayouts[tablayoutid].tabControllerRef.getCurrentTabRef();
} else {
alert("[Invalid tablayoutID]");
return;
}
}

return {
createLayout,
getSelectedTabAtLayout,
}
}
250 changes: 250 additions & 0 deletions js/layoutcontrols/tabControls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
// numOfTabLayouts = 0 //this is global variable. Wrap this in a function later.


//This is going to be the main function class which will coordinate all tab related operations.
function TabController(numTabs=0, tablayoutId=0) {
let myTabLayoutId = tablayoutId;
let nTabs = numTabs;
const activeTabIds = new Set();

//this will hold the html ref for the currently selected tab. To be used by other modules for context management.
let selectedTabRef = {
container : null,
tabButton : null,
}

function initTabLayout (tabContainerRef) {
if (!tabContainerRef) alert("[Undefined Reference] Cannot create a tab layout without the container reference.");

const tabEditor = getTabParentContainers(myTabLayoutId);
let tabs = null;

for (let tn=1; tn<=nTabs; tn++){
tabs = getTabDivPair(tn, myTabLayoutId);

tabEditor.editorContainer.appendChild(tabs.tabcontent);
tabEditor.linkContainer.appendChild(tabs.tablink);

addTabId(tn);
}

console.log(tabEditor);

//add the add more button
tabEditor.linkContainer.appendChild(getAddTabButton(myTabLayoutId));

//Insert the tab layout in the DOM.
tabContainerRef.appendChild(tabEditor.navBar);
tabContainerRef.appendChild(tabEditor.editorContainer);
tabContainerRef.appendChild(tabEditor.linkContainer);

// //incr the global counter.
// numOfTabLayouts++;
return tabEditor;
}

function doHydrate(tabEditorRef, tabControllerRef=null) {
console.log ("do hydration is called.");
if (!tabEditorRef) {
alert("[Undefined Reference] Cannot hydrate without tabEditor ref.");
return;
}

handleTabEvents = tabEventHandlers();

console.log(tabEditorRef);
console.log(tabControllerRef);

if (tabEditorRef) {
for (const cn of tabEditorRef.linkContainer.children) {
if (cn.id.startsWith(`layout${myTabLayoutId}.tab-file`)){
cn.addEventListener('click', () => handleTabEvents.openTabHandler(cn, tabControllerRef)); //Attach select this tab handler.
cn.lastChild.addEventListener('click', (evt) => handleTabEvents.closeTabHandler(evt, cn.lastChild, tabControllerRef)); //attach close tab handler.
}
if (cn.id === `layout${myTabLayoutId}.add_tab`) {
cn.addEventListener('click', () => handleTabEvents.addTabHandler(cn, tabControllerRef));
}
}

}
console.log("hydration is finished.");
}
//Setup the tab layout and hydrate it.
// doHydrate(); //Moving this as a step for initTabLayout.

function getMyTabLayoutId () {
return myTabLayoutId;
}

function incrTabs () {
nTabs += 1;
}
function decrTabs () {
nTabs -= 1;
}

function totalOpenTabs () {
return nTabs;
}

function getNewTabId () {
let tabid = 0;
while (activeTabIds.has(++tabid));
// activeTabIds.add(numTabs); //dont add here. add after the creation is successful.
return tabid;

}

function addTabId (tabId) {
//todo : sanity checks to be added and fallbacks to be implemented.
activeTabIds.add(tabId);
}

function remmoveTabId (tabId) {
activeTabIds.delete(tabId);
}

function selectThisTab (tabButtonRef, doClick = true) {
if (doClick) {
tabButtonRef.click();
tabButtonRef.focus();
}
selectedTabRef.tabButton = tabButtonRef;
selectedTabRef.container = getContainerForTab(tabButtonRef);
}

function closeThisTab(closeTabRef) {
const buttonTabRef = closeTabRef.parentNode;
let prevTabButtonRef = null;

if (buttonTabRef === selectedTabRef.tabButton) {
//We are trying to close the tab which is selected. We need to move the focus to the previous tab.
prevTabButtonRef = buttonTabRef.previousSibling;
}
const editorTabRef= getContainerForTab(buttonTabRef);

//We have the refs to both button and the editor. Remove them and click the prevTabButton is it exists.
editorTabRef.remove();
buttonTabRef.remove();

//hacking this now. Implement a proper tabid structure to stop having to write messy code.
let tabid = closeTabRef.id.split('.')[1].split('file')[1];
console.log(tabid);
remmoveTabId(parseInt(tabid));
decrTabs();

if (prevTabButtonRef) {
selectThisTab(prevTabButtonRef);
}
}
function getCurrentTabRef () {
return selectedTabRef;
}

return {
myTabLayoutId,
selectedTabRef,
incrTabs,
totalOpenTabs,
selectThisTab,
getCurrentTabRef,
initTabLayout,
doHydrate,
getMyTabLayoutId,
closeThisTab,
getNewTabId,
addTabId,
remmoveTabId,
};
}

//This will hold all tab related event handlers.
function tabEventHandlers () {
console.log("tab event handler instantiated.");

const openTabHandler = (element, tcRef = null) => {
if (!tcRef) {
alert("[Undefined Reference] TabController instance missing.");
return;
}

console.log("open tab got called.");
console.log("element ref i got is : ", element);

let layout_class_name = `belongs_to_layout_${tcRef.getMyTabLayoutId()}`;

//Hide all the tabs
tabcontent = document.getElementsByClassName(`tabcontent ${layout_class_name}`);

console.log("filtered tab contents : ", tabcontent);

for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}

//Uncolor all the tab selectors
tablinks = document.getElementsByClassName(`tablink ${layout_class_name}`);
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
tablinks[i].classList.remove("selected_tab_button");
}

const tabcontentToHighlight = getContainerForTab(element);
console.log(tabcontentToHighlight);

tabcontentToHighlight.style.display = "block";
element.classList.add("selected_tab_button");

tcRef.selectThisTab(element, doClick=false);
}

const addTabHandler = (element, tcRef) => {
if (!tcRef) {
alert("[Undefined Reference] TabController instance missing.");
return;
}

let fileNum = 0;
console.log(tcRef.totalOpenTabs());

// tcRef.incrTabs();
fileNum = tcRef.getNewTabId();

tablink_container = element.parentNode;
tab_container = tablink_container.previousSibling;


const tabInfo = getTabDivPair(fileNum, tcRef.getMyTabLayoutId());

const div_tab = tabInfo.tabcontent;
const button_tab = tabInfo.tablink;
const close_tab = tabInfo.closetab;

button_tab.addEventListener('click', () => openTabHandler(button_tab, tcRef));
close_tab.addEventListener('click', (evt) => closeTabHandler(evt, close_tab, tcRef));

tab_container.appendChild(div_tab);
tablink_container.insertBefore(button_tab, element);
tcRef.addTabId(fileNum);

//click the newly added button to select it.
tcRef.selectThisTab(button_tab);
}

function closeTabHandler(evt, element, tcRef) {
if (!tcRef) {
alert("[Undefined Reference] TabController instance missing.");
return;
}
evt.stopPropagation();

tcRef.closeThisTab(element);

}

return {
openTabHandler,
addTabHandler,
closeTabHandler,
}
}
40 changes: 40 additions & 0 deletions js/primitive/tab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

//This is our primitive. Will hold all the information and operations pertaining to a particular tab.
function Tab (tabId) {

//todo : validate the tabId.
let tabref = document.getElementById(tabId);

function setCursorAt() {

}

function getCursorLocation () {

}

function getNumberOfCharacters () {

}

function getNumOfLines () {

}

function applyUndo () {

}

function applyRedo () {

}

return {
setCursorAt,
getCursorLocation,
getNumberOfCharacters,
getNumOfLines,
applyUndo,
applyRedo,
}
}
Loading

0 comments on commit baf12e0

Please sign in to comment.