forked from pranjay-poddar/Dev-Geeks
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
uploaded the required stuffs
- Loading branch information
Showing
14 changed files
with
699 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Sessions | ||
|
||
Save chrome tabs as sessions | ||
|
||
![ezgif-3-e09ce27683](https://user-images.githubusercontent.com/42151354/162585583-c35a0b64-7632-470a-89b9-c5282714d5de.gif) | ||
|
||
## Functions Available | ||
--- | ||
|
||
1. User can create workspaces from open tabs in just one click. | ||
2. The sessions can be restored at any time. They will stored in local storage and will not be erased. | ||
3. Ability to name sessions, restore and delete them. | ||
4. Effective memory management. | ||
|
||
## Technologies Used | ||
--- | ||
1. HTML/CSS and JS | ||
2. Moment.js for date and time parsing | ||
|
||
## How to Install | ||
--- | ||
1. Clone this repository | ||
2. Open chrome and go to chrome://extensions/ and turn on Developer mode | ||
3. Click on "Load unpacked" and load the cloned repository | ||
4. The extension will be now available on chrome | ||
5. Still getting stuck ? Check this website for help: <a href="https://www.cnet.com/tech/services-and-software/how-to-install-chrome-extensions-manually/">Manually install extensions</a> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
document.addEventListener("DOMContentLoaded", () => { | ||
display(); | ||
attachEventSaveTabs(); | ||
attachClickListener(); | ||
addEventListenerForPersistChange(); | ||
addEventListenerForSaveName(); | ||
}) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
const cardListDiv = document.querySelector('.sessionContainer'); | ||
|
||
const buildCard = (cardDetails, indexOfCard) => { | ||
const cardSectionDiv = document.createElement('div'); | ||
cardSectionDiv.id = "card-section-" + indexOfCard; | ||
|
||
const nameDiv = buildNameDiv(indexOfCard, cardDetails.name); | ||
cardSectionDiv.appendChild(nameDiv); | ||
|
||
const div = document.createElement("div"); | ||
div.classList.add("card"); | ||
|
||
const header = buildHeader(cardDetails.createdAt, cardDetails.noOfTabs); | ||
div.appendChild(header); | ||
|
||
const content = buildContent(cardDetails.titles, cardDetails.favIconUrls); | ||
div.appendChild(content); | ||
|
||
const footer = buildFooter(indexOfCard, cardDetails.persist); | ||
div.appendChild(footer); | ||
|
||
cardSectionDiv.appendChild(div); | ||
cardListDiv.appendChild(cardSectionDiv); | ||
|
||
let illustrationDom = document.querySelector('.illustration'); | ||
illustrationDom.style.display = "none"; | ||
|
||
let textDom = document.querySelector('.textContent'); | ||
textDom.style.display = "none"; | ||
|
||
} | ||
|
||
const buildNameDiv = (indexOfCard, cardName) => { | ||
let rowDiv = document.createElement("div"); | ||
rowDiv.classList.add("row", "name-row-div"); | ||
let nameBtn = document.createElement("button"); | ||
nameBtn.classList.add("name-btn"); | ||
if (cardName) { | ||
nameBtn.style.display = "block" | ||
nameBtn.textContent = cardName; | ||
nameBtn.disabled = true; | ||
rowDiv.appendChild(nameBtn); | ||
return rowDiv; | ||
} | ||
|
||
let nameTextBox = document.createElement('input'); | ||
nameTextBox.setAttribute("type", "text inline"); | ||
nameTextBox.setAttribute("placeholder", "Enter name"); | ||
nameTextBox.classList.add("name-text-box", "hide-element"); | ||
nameTextBox.id = "name-" + indexOfCard; | ||
nameTextBox.style.display = "none"; | ||
|
||
let saveNameBtn = document.createElement("button"); | ||
saveNameBtn.classList.add("name-save-btn", "hide-element"); | ||
saveNameBtn.textContent = "Save"; | ||
saveNameBtn.id = "saveBtn-" + indexOfCard; | ||
saveNameBtn.style.display = "none"; | ||
|
||
nameBtn.textContent = "Enter Session Name"; | ||
nameBtn.addEventListener('click', function() { | ||
if(nameTextBox.classList.contains("hide-element")) { | ||
nameTextBox.style.display = "block"; | ||
saveNameBtn.style.display = "block"; | ||
nameBtn.style.display = "none" | ||
} | ||
}); | ||
|
||
rowDiv.appendChild(nameBtn); | ||
rowDiv.appendChild(nameTextBox); | ||
rowDiv.appendChild(saveNameBtn); | ||
|
||
return rowDiv; | ||
} | ||
|
||
|
||
const buildHeader = (createdAt, noOfTabs) => { | ||
let headerDiv = document.createElement('div'); | ||
headerDiv.classList.add("header", "row"); | ||
|
||
let dateDiv = document.createElement('div'); | ||
dateDiv.classList.add("date", "col", "s6"); | ||
dateDiv.textContent = moment(createdAt).fromNow(); | ||
headerDiv.appendChild(dateDiv); | ||
|
||
let noOfTabsDiv = document.createElement('div'); | ||
noOfTabsDiv.classList.add("noOfTabs", "col", "s6"); | ||
noOfTabsDiv.textContent = noOfTabs + " Tabs"; | ||
headerDiv.appendChild(noOfTabsDiv); | ||
|
||
return headerDiv; | ||
} | ||
|
||
const buildContent = function(tabTitles, favIconUrls) { | ||
const container = document.createElement('div'); | ||
container.classList.add("card-content"); | ||
|
||
const list = document.createElement('ul'); | ||
list.classList.add("collection"); | ||
|
||
let count=0; | ||
for(count ; count < tabTitles.length && count < 3; ++count) { // Display upto three tabs | ||
let item = document.createElement('li'); | ||
item.classList.add("collection-item"); | ||
|
||
let icon = document.createElement('img'); | ||
icon.setAttribute("src", favIconUrls[count]); | ||
item.appendChild(icon); | ||
|
||
|
||
let textNode = document.createTextNode(tabTitles[count]); | ||
item.appendChild(textNode); | ||
list.appendChild(item); | ||
} | ||
|
||
container.appendChild(list); | ||
return container; | ||
} | ||
|
||
const buildFooter = function(indexOfCard, is_card_persisted) { | ||
const div = document.createElement('div'); | ||
div.classList.add("card-action"); | ||
|
||
const restore = document.createElement('a'); | ||
restore.classList.add("actionBtn", "restore"); | ||
restore.setAttribute("href", "#"); | ||
restore.textContent = "Restore"; | ||
restore.id = "restore-" + indexOfCard; | ||
div.appendChild(restore); | ||
|
||
const del = document.createElement('a'); | ||
del.classList.add("actionBtn", "del"); | ||
del.setAttribute("href", "#"); | ||
del.textContent = "Delete"; | ||
del.id = "del-" + indexOfCard; | ||
div.appendChild(del); | ||
|
||
const persistLabel = document.createElement('label'); | ||
persistLabel.setAttribute("for", indexOfCard.toString()); | ||
|
||
const persistCheckBox = document.createElement('input'); | ||
persistCheckBox.setAttribute("type", "checkbox"); | ||
persistCheckBox.id = indexOfCard.toString(); | ||
if (is_card_persisted) { | ||
persistCheckBox.setAttribute("checked", "checked"); | ||
} | ||
persistLabel.appendChild(persistCheckBox); | ||
|
||
const persistSpan = document.createElement('span'); | ||
persistSpan.textContent = "Do not remove"; | ||
persistLabel.appendChild(persistSpan); | ||
|
||
div.appendChild(persistLabel); | ||
|
||
return div; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
const addEventListenerForPersistChange = () => { | ||
let checkboxes = document.querySelectorAll('input[type=checkbox]'); | ||
checkboxes.forEach((checkbox) => checkbox.addEventListener('change', sessionPersistanceSetting)); | ||
} | ||
|
||
const addEventListenerForSaveName = () => { | ||
let saveCardNameButtons = document.querySelectorAll('button.name-save-btn'); | ||
saveCardNameButtons.forEach((button) => button.addEventListener('click', saveCardName)); | ||
} | ||
|
||
const attachClickListener = () => { | ||
cardListDiv.addEventListener('click', function(event) { | ||
|
||
// return if there is no action button | ||
|
||
if(!event.target.classList.contains("actionBtn")) | ||
return; | ||
|
||
// action button on the card list was clicked | ||
|
||
const clickedElement = event.target; | ||
if(clickedElement.classList.contains('restore')) | ||
restore(clickedElement); | ||
else | ||
deleteCard(clickedElement); | ||
}); | ||
} | ||
|
||
const deleteCard = (deleteBtn) => { | ||
const indexOfClickedCard = parseInt(deleteBtn.id.substring(4), 10); | ||
|
||
// Remove the card from DOM | ||
|
||
let clickedCard = document.querySelector("#card-section-" + indexOfClickedCard); | ||
clickedCard.remove(); | ||
location.href = "popup.html"; | ||
|
||
// Update stored data | ||
|
||
const savedData = JSON.parse(localStorage.getItem('data')); | ||
savedData.splice(indexOfClickedCard, 1); | ||
localStorage.setItem('data', JSON.stringify(savedData)); | ||
} | ||
|
||
const restore = function(restoreBtn) { | ||
const savedData = JSON.parse(localStorage.getItem('data')); | ||
const indexOfClickedCard = parseInt(restoreBtn.id.substring(8), 10); | ||
|
||
// Find the tab which is active when the button is clicked | ||
|
||
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) { | ||
let currentIndex = tabs[0].index; // Record its index | ||
|
||
savedData[indexOfClickedCard].urls.forEach(url => { // Fire up the stored tabs | ||
chrome.tabs.create({url: url}); | ||
}); | ||
|
||
if(currentIndex !== null) { | ||
chrome.tabs.highlight({tabs: currentIndex}); // The tab which the user was using should be in focus. } | ||
}; | ||
|
||
if (!savedData[indexOfClickedCard].persist) { | ||
|
||
// Remove the card from DOM | ||
|
||
let clickedCard = document.querySelector("#card-section-" + indexOfClickedCard); | ||
clickedCard.remove(); | ||
|
||
// Update stored data | ||
|
||
savedData.splice(indexOfClickedCard, 1); | ||
localStorage.setItem('data', JSON.stringify(savedData)); | ||
} | ||
}); | ||
} | ||
|
||
const sessionPersistanceSetting = function(event) { | ||
const indexOfCard = event.target.id; | ||
const savedTabGroups = JSON.parse(localStorage.getItem('data')); | ||
|
||
let indexToInsertAt; | ||
if (!event.target.checked) { | ||
indexToInsertAt = savedTabGroups.findIndex((tabGroup) => !tabGroup.persist); | ||
} | ||
|
||
savedTabGroups[indexOfCard].persist = event.target.checked; // Update persistence status | ||
|
||
if (event.target.checked) { | ||
// Card has to be persisted. Move the persisted card to the top of the list | ||
if (indexOfCard > 0) { | ||
savedTabGroups.unshift(savedTabGroups.splice(indexOfCard, 1)[0]); | ||
} | ||
} else { | ||
// Don't persist this card anymore. Move the card to the first position after the persisted cards | ||
if (savedTabGroups.length > 1) { | ||
if (indexToInsertAt == -1) { | ||
savedTabGroups.push(savedTabGroups.splice(indexOfCard, 1)[0]); // Insert at the end | ||
} else { | ||
indexToInsertAt--; // Since we insert after first removing the element from the array | ||
savedTabGroups.splice(indexToInsertAt, 0, savedTabGroups.splice(indexOfCard, 1)[0]); | ||
} | ||
} | ||
} | ||
|
||
localStorage.setItem('data', JSON.stringify(savedTabGroups)); | ||
} | ||
|
||
const saveCardName = (event) => { | ||
let idString = event.target.id; | ||
const indexOfCardClicked = parseInt(idString.substring(8), 10); // saveBtn- is 8 character long | ||
|
||
let nameTextBox = document.querySelector("#name-" + indexOfCardClicked); | ||
const enteredName = nameTextBox.value; | ||
if (enteredName) { | ||
const savedTabGroups = JSON.parse(localStorage.getItem('data')); | ||
savedTabGroups[indexOfCardClicked].name = enteredName; | ||
localStorage.setItem('data', JSON.stringify(savedTabGroups)); | ||
} | ||
location.href = "popup.html"; | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
const display = () => { | ||
|
||
// Load data from the local storage | ||
|
||
const localStorageData = JSON.parse(localStorage.getItem('data')); | ||
|
||
// Array does not exists or is empty | ||
|
||
if((!Array.isArray(localStorageData)) || (localStorageData.length === 0)) { | ||
return; | ||
} | ||
|
||
// Display data from local storage | ||
|
||
localStorageData.forEach((tabGroup, index) => { | ||
buildCard(tabGroup, index); | ||
}); | ||
} |
Oops, something went wrong.