photo-assistant
Advanced tools
Comparing version 1.0.1 to 2.0.0
// Main entry point. | ||
import { PhotoAssistant } from './photoAssistant/photoAssistant.js' | ||
import { PhotoAssistantOrchestrator } from './photoAssistant/photoAssistant.js' | ||
export { PhotoAssistant } | ||
export { PhotoAssistantOrchestrator } |
@@ -5,3 +5,3 @@ /** | ||
* @author Sabrina Prichard-Lybeck <sp223kz@student.lnu.se> | ||
* @version 1.0.0 | ||
* @version 2.0.0 | ||
*/ | ||
@@ -25,6 +25,2 @@ export class PhotoCanvasCreator { | ||
/** | ||
* | ||
* @param {HTMLImageElement} imageToBeDrawn | ||
*/ | ||
_runPhotoCanvasCreator(imageToBeDrawn, canvasId) { | ||
@@ -38,3 +34,2 @@ if (imageToBeDrawn === null || imageToBeDrawn === undefined || imageToBeDrawn.src.length === 0) { | ||
this.#imageToBeDrawn = imageToBeDrawn | ||
this.#imageToBeDrawn.onload = this.#createCanvas(canvasId) | ||
@@ -45,7 +40,2 @@ this.#drawPhotoToCanvas() | ||
/** | ||
* Method to create a blank canvas. | ||
* | ||
* @param {string} canvasId | ||
*/ | ||
#createCanvas(canvasId) { | ||
@@ -62,3 +52,2 @@ // Setup an empty canvas. | ||
// Extract the CSS filter value from the image (if the image has a filter effect) and add it to the canvas drawn version of the image (to enable user to view and save filtered images). | ||
if (this.#imageToBeDrawn.style.filter) { | ||
@@ -65,0 +54,0 @@ const filter = this.#imageToBeDrawn.style.filter |
@@ -5,18 +5,11 @@ /** | ||
* @author Sabrina Prichard-Lybeck <sp223kz@student.lnu.se> | ||
* @version 1.0.0 | ||
* @version 2.0.0 | ||
*/ | ||
export class PhotoFilter { | ||
#image | ||
#filterMethod = '' | ||
#filterValue = '' | ||
#chosenFilters = [] | ||
#filters = '' | ||
#multipleFilters = '' | ||
#image | ||
/** | ||
* Entry point method which invokes the filterPhoto method. | ||
* | ||
* @param {HTMLImageElement} image - the image to be filtered. | ||
* @param {string} filterMethod | ||
* @param {string} filterValue | ||
*/ | ||
_runAddFilters (filterMethod, filterValue) { | ||
@@ -30,2 +23,11 @@ if (typeof (filterMethod) !== 'string' || typeof (filterValue) !== 'string' || filterMethod === undefined || filterValue === undefined) { | ||
#addChosenFilterMethods (filterMethod, filterValue) { | ||
const filter = { | ||
filterMethod, | ||
filterValue | ||
} | ||
this.#chosenFilters.push(filter) | ||
} | ||
_runApplyFilters (image) { | ||
@@ -45,11 +47,2 @@ if (image === null || image === undefined || image.src.length === 0) { | ||
#addChosenFilterMethods (filterMethod, filterValue) { | ||
const filter = { | ||
filterMethod, | ||
filterValue | ||
} | ||
this.#chosenFilters.push(filter) | ||
} | ||
#applyFilters () { | ||
@@ -72,24 +65,3 @@ if (this.#chosenFilters.length === 0) { | ||
} | ||
#runApplyMultipleFilters () { | ||
this.#chosenFilters.forEach((filter) => { | ||
this.#filterMethod = filter.filterMethod | ||
this.#filterValue = filter.filterValue | ||
this.#constructFilterString() | ||
this.#addMultipleFilters() | ||
}) | ||
} | ||
#constructFilterString () { | ||
if (this.#filterMethod === 'blur') { | ||
this.#filters += `${this.#filterMethod}(${this.#filterValue}px) ` | ||
} else { | ||
this.#filters += `${this.#filterMethod}(${this.#filterValue}%) ` | ||
} | ||
} | ||
/** | ||
* Method that delegates image filtering to the correct filter method. | ||
* | ||
*/ | ||
#singleFilterPhotoManager () { | ||
@@ -123,6 +95,2 @@ switch (this.#filterMethod.toLowerCase()) { | ||
/** | ||
* Method that updates the exposure/brightness of an image. | ||
* | ||
*/ | ||
#updateBrightness () { | ||
@@ -132,6 +100,2 @@ this.#image.style.filter = `brightness(${this.#filterValue}%)` | ||
/** | ||
* Method that updates the saturation of an image. | ||
* | ||
*/ | ||
#updateSaturation () { | ||
@@ -141,6 +105,2 @@ this.#image.style.filter = `saturate(${this.#filterValue}%)` | ||
/** | ||
* Method that updates the opacity of an image. | ||
* | ||
*/ | ||
#updateOpacity () { | ||
@@ -150,6 +110,2 @@ this.#image.style.filter = `opacity(${this.#filterValue}%)` | ||
/** | ||
* Method adds sepia to an image. | ||
* | ||
*/ | ||
#addSepia () { | ||
@@ -159,6 +115,2 @@ this.#image.style.filter = `sepia(${this.#filterValue}%)` | ||
/** | ||
* Method that updates the contrast of an image. | ||
* | ||
*/ | ||
#updateContrast () { | ||
@@ -168,6 +120,2 @@ this.#image.style.filter = `contrast(${this.#filterValue}%)` | ||
/** | ||
* Method that adds blur to an image. | ||
* | ||
*/ | ||
#addBlur () { | ||
@@ -177,6 +125,2 @@ this.#image.style.filter = `blur(${this.#filterValue}px)` | ||
/** | ||
* Method that adds grayscale to an image. | ||
* | ||
*/ | ||
#addGrayscale () { | ||
@@ -186,5 +130,22 @@ this.#image.style.filter = `grayscale(${this.#filterValue}%)` | ||
#runApplyMultipleFilters () { | ||
this.#chosenFilters.forEach((filter) => { | ||
this.#filterMethod = filter.filterMethod | ||
this.#filterValue = filter.filterValue | ||
this.#constructFilterString() | ||
this.#addMultipleFilters() | ||
}) | ||
} | ||
#constructFilterString () { | ||
if (this.#filterMethod === 'blur') { | ||
this.#multipleFilters += `${this.#filterMethod}(${this.#filterValue}px) ` | ||
} else { | ||
this.#multipleFilters += `${this.#filterMethod}(${this.#filterValue}%) ` | ||
} | ||
} | ||
#addMultipleFilters () { | ||
this.#image.style.filter = this.#filters | ||
this.#image.style.filter = this.#multipleFilters | ||
} | ||
} |
@@ -5,8 +5,8 @@ /** | ||
* @author Sabrina Prichard-Lybeck <sp223kz@student.lnu.se> | ||
* @version 1.0.0 | ||
* @version 2.0.0 | ||
*/ | ||
export class PhotoGallery { | ||
#images = [] | ||
#gridColumns | ||
#gridRows | ||
#images = [] | ||
#galleryContainer | ||
@@ -34,20 +34,3 @@ | ||
} | ||
/** | ||
* Method to render gallery after creation. | ||
* | ||
* @param {HTMLElement} appendGalleryTo - element to which the created grid gallery will be appended. | ||
*/ | ||
_renderGallery (appendGalleryTo) { | ||
if (this.#galleryContainer !== null) { | ||
appendGalleryTo.appendChild(this.#galleryContainer) | ||
} else { | ||
throw new Error('There is no gallery yet created to be rendered') | ||
} | ||
} | ||
/** | ||
* Creates a grid gallery layout by calculating the grid size by taking the grid columns as an argument and calculating the needed grid row size to fit the selected amount of photos. | ||
* | ||
*/ | ||
#createGridGallery () { | ||
@@ -69,2 +52,10 @@ const numberOfPhotos = this.#images.length | ||
} | ||
_renderGallery (appendGalleryTo) { | ||
if (this.#galleryContainer !== null) { | ||
appendGalleryTo.appendChild(this.#galleryContainer) | ||
} else { | ||
throw new Error('There is no gallery yet created to be rendered') | ||
} | ||
} | ||
} |
@@ -5,9 +5,9 @@ /** | ||
* @author Sabrina Prichard-Lybeck <sp223kz@student.lnu.se> | ||
* @version 1.0.0 | ||
* @version 2.0.0 | ||
*/ | ||
export class PhotoSort { | ||
#imageAlts = [] | ||
#alphabeticallySortedAlts = [] | ||
#imagesToBeSorted = [] | ||
#imageAlts = [] | ||
#sortedAlts = [] | ||
#sortedImages = [] | ||
#alphabeticallySortedImages = [] | ||
@@ -25,7 +25,2 @@ /** | ||
/** | ||
* Entry point method. | ||
* | ||
* @returns {Array} sortedImages | ||
*/ | ||
_runPhotoSorting () { | ||
@@ -36,7 +31,7 @@ this.#extractAltsFromPhotos() | ||
if (this.#sortedImages === null || this.#sortedImages.length === 0) { | ||
if (this.#alphabeticallySortedImages === null || this.#alphabeticallySortedImages.length === 0) { | ||
throw new Error('There was an error sorting the images') | ||
} | ||
return this.#sortedImages | ||
return this.#alphabeticallySortedImages | ||
} | ||
@@ -52,12 +47,11 @@ | ||
#sortPhotosByAlphabet () { | ||
this.#sortedAlts = this.#imageAlts.toSorted() | ||
this.#alphabeticallySortedAlts = this.#imageAlts.toSorted() | ||
} | ||
#matchSortedAltsToImg () { | ||
// Find the HTML img element with a matching alt, push the img elementsinto the sortedArray in the same order as the sorted alts. | ||
for (let i = 0; i < this.#imagesToBeSorted.length; i++) { | ||
const match = this.#imagesToBeSorted.find(image => image.alt === this.#sortedAlts[i]) | ||
this.#sortedImages.push(match) | ||
const match = this.#imagesToBeSorted.find(image => image.alt === this.#alphabeticallySortedAlts[i]) | ||
this.#alphabeticallySortedImages.push(match) | ||
} | ||
} | ||
} |
@@ -5,13 +5,8 @@ /** | ||
* @author Sabrina Prichard-Lybeck <sp223kz@student.lnu.se> | ||
* @version 1.0.0 | ||
* @version 2.0.0 | ||
*/ | ||
export class PhotoStorage { | ||
/** | ||
* Save an image to and retrieve an image (new image element) from local storage. | ||
* | ||
* @param {HTMLImageElement} image | ||
*/ | ||
_saveImage (image) { | ||
if (image.alt === undefined || image.alt.length === 0) { | ||
throw new Error('Image alt cannot be null or empty. Alt description is required.') | ||
throw new Error('Alt description is required for all images') | ||
} if (image === null || image === undefined || image.src.length === 0) { | ||
@@ -24,8 +19,9 @@ throw new Error('Invalid image') | ||
/** | ||
* Fetch an image from local storage. | ||
* | ||
* @param {string} imageDescription - image alt text. | ||
* @returns {HTMLImageElement} newImage - new image created with original image's source which has been stored and retrieved from local storage. | ||
*/ | ||
#saveImageToStorage (image) { | ||
const imageAlt = image.alt | ||
const imageUrl = image.src | ||
localStorage.setItem(imageAlt, imageUrl) | ||
} | ||
_getImage (imageDescription) { | ||
@@ -41,34 +37,12 @@ if (typeof (imageDescription) !== 'string' || imageDescription === undefined || imageDescription.length === 0) { | ||
/** | ||
* Method to clear all images from storage. | ||
*/ | ||
_clearStorage () { | ||
localStorage.clear() | ||
} | ||
#getImageFromStorage (imageDescription) { | ||
const fetchedImageUrl = localStorage.getItem(imageDescription) | ||
const newImage = this.#createNewImage(fetchedImageUrl, imageDescription) | ||
/** | ||
* Takes the reference to the original image element and extracts the url from it for storage, which will later be used to construct a new image element that can be used for manipulation. | ||
* | ||
* @param {HTMLImageElement} image - image to be stored. | ||
*/ | ||
#saveImageToStorage (image) { | ||
const name = image.alt | ||
const imageUrl = image.src | ||
// Image element is deconstructed and only the extracted image src stored to "break reference" to the original image element and simplify data storaging. | ||
localStorage.setItem(name, imageUrl) | ||
return newImage | ||
} | ||
/** | ||
* Retrieves an image from storage by its url and constructs a new image element from it. | ||
* | ||
* @param {string} imageDescription - the alt text of the image to be retrieved which also corresponds to the image key saved in storage. | ||
* @returns {HTMLImageElement} newImage - new image which has been created from original image's source. | ||
*/ | ||
#getImageFromStorage (imageDescription) { | ||
const fetchedImageUrl = localStorage.getItem(imageDescription) | ||
// New image element is constructed for later manipulation, to create an independence from the original image element. | ||
#createNewImage (imageUrl, imageDescription) { | ||
const newImage = new Image() | ||
newImage.src = fetchedImageUrl | ||
newImage.src = imageUrl | ||
newImage.alt = imageDescription | ||
@@ -78,2 +52,6 @@ | ||
} | ||
_clearAllPhotosFromStorage () { | ||
localStorage.clear() | ||
} | ||
} |
{ | ||
"name": "photo-assistant", | ||
"version": "1.0.1", | ||
"version": "2.0.0", | ||
"main": "lib/index.js", | ||
@@ -5,0 +5,0 @@ "exports": { |
# Photo Assistant | ||
Photo Assistant is a dependency-free library written in vanilla JavaScript (ES6) that provides simple photo editing, photo sorting (alphabetically based on img alt) and photo gallery displaying of HTML img elements. It also stores image urls in local storage for easy access and retrieval and offers drawing of edited images on a canvas element to enable saving of edited images. | ||
Photo Assistant is a dependency-free library written in vanilla JavaScript (ES6) that provides simple photo editing, photo sorting (alphabetically based on img alt) and photo gallery displaying of HTML img elements. It also stores image urls in local storage for easy access and retrieval and offers drawing of edited images onto a canvas element to enable saving of edited images. | ||
@@ -17,12 +17,12 @@ Photo Assistant's USP (unique selling point) is that it offers all of these features within the same library, making it useful for a range of applications handling images such as photography portfolio websites, blogs, social media platforms etc. It is also lightweight and easy to use. | ||
To use Photo Assistant, import the library into your project: | ||
To use Photo Assistant, import the library orchestrator into your project: | ||
```javascript | ||
import { PhotoAssistant } from 'photo-assistant' | ||
import { PhotoAssistantOrchestrator } from 'photo-assistant' | ||
``` | ||
Then, create a new instance of the PhotoAssistant class: | ||
Then, create a new instance of the PhotoAssistantOrchestrator class: | ||
```javascript | ||
const photoAssistant = new PhotoAssistant() | ||
const photoAssistant = new PhotoAssistantOrchestrator() | ||
``` | ||
@@ -33,3 +33,3 @@ | ||
```javascript | ||
document.addEventListener { | ||
document.addEventListener ('click', (event) => { | ||
const images = document.querySelectorAll('img') | ||
@@ -42,5 +42,7 @@ | ||
} | ||
} | ||
}) | ||
``` | ||
! `img alt` description is **required** to add and handle images with PhotoAssistant ! | ||
### Edit photos by adding filters | ||
@@ -50,6 +52,7 @@ | ||
To filter images that have been added to PhotoAssistant (se previous instruction on how to get started) you need to first invoke the `startPhotoFilter()` method, which will create an instance of PhotoFilter(). Then add a single or multiple filters with the `chosenFiltersToAdd(filterMethod, filterValue)` method. Finally, apply the chosen filters to the images: | ||
![Image with filters added](./test/test-images/photoAssistantFilters.jpg) | ||
To filter images that have been added to PhotoAssistant you add a single or multiple filters with the `chosenFiltersToAdd(filterMethod, filterValue)` method and then apply the chosen filters to the images: | ||
```javascript | ||
photoAssistant.startPhotoFilter() | ||
@@ -77,3 +80,2 @@ photoAssistant.chosenFiltersToAdd(filterMethod, filterValue) | ||
photoAssistant.startPhotoFilter() | ||
photoAssistant.chosenFiltersToAdd(filterMethod, filterValue) | ||
@@ -105,4 +107,12 @@ photoAssistant.applyChosenFilters() | ||
Draw an image that has been filtered to a canvas element using PhotoAssistant by invoking the `drawPhotosToCanvas(appendCanvasTo, canvasId)` method. An HTML element to which the canvas element will be appended is sent as the first argument and you give the canvas an id with the second argument. | ||
Draw an image that has been filtered to a canvas element using PhotoAssistant by invoking the `drawPhotosToCanvas(appendCanvasTo, canvasId)` method. | ||
![Example of image drawn to canvas](./test/test-images/nara-filtered.png) | ||
An HTML element to which the canvas element will be appended is sent as the first argument and you give the canvas an id with the second argument. | ||
For more information about the Canvas API view the documentation: | ||
[Canvas API MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) | ||
```javascript | ||
@@ -127,2 +137,4 @@ // After filtering images. | ||
![Images displayed in a grid gallery](./test/test-images/gallery-in-original-order.png) | ||
To display photos in a grid gallery the `displayPhotosInGallery(columns, galleryContainer)` method is used. | ||
@@ -129,0 +141,0 @@ |
@@ -1,12 +0,18 @@ | ||
import { PhotoAssistant } from '../../../lib/photoAssistant/photoAssistant.js' | ||
import { PhotoAssistantOrchestrator } from '../../../lib/photoAssistant/photoAssistantOrchestrator.js' | ||
// The following code is a simple example of how PhotoAssistant can be used and has also been created for testing purposes. | ||
document.addEventListener('DOMContentLoaded', () => { | ||
// HTML img elements can be sent to PhotoAssistant by selecting img elements already in the document. | ||
const images = document.querySelectorAll('img') | ||
const filterImageForm = document.getElementById('filter-image-form') | ||
const galleryForm = document.getElementById('gallery-form') | ||
const photoAssistant = new PhotoAssistant() | ||
// Instantiate PhotoAssistant. | ||
const photoAssistant = new PhotoAssistantOrchestrator() | ||
// Add event listener to listen to click events on images already in the document to add them to PhotoAssistant. | ||
for (let i = 0; i < images.length; i++) { | ||
images[i].addEventListener('click', (event) => { | ||
photoAssistant.addImage(images[i]) | ||
photoAssistant.saveImage(images[i]) | ||
images[i].style.filter = 'opacity(40%)' | ||
@@ -16,2 +22,3 @@ }) | ||
// Use a submit form to trigger filtering of photos. | ||
filterImageForm.addEventListener('submit', (event) => { | ||
@@ -36,2 +43,3 @@ event.preventDefault() | ||
// Test code to fetch an image that has been stored in local storage via PhotoAssistant. | ||
const imgAlt = 'Glico man billboard in Dotonbori in Osaka, Japan' | ||
@@ -42,3 +50,3 @@ photoAssistant.getStoredPhoto(imgAlt) | ||
photoAssistant.startPhotoFilter() | ||
// Add and apply the filters that have been submitted via the form. | ||
photoAssistant.chosenFiltersToAdd(filterMethod, filterValue) | ||
@@ -50,5 +58,7 @@ photoAssistant.applyChosenFilters() | ||
// Draw the filtered image to a canvas element (to enable saving of the filtered image). | ||
photoAssistant.drawPhotosToCanvas(canvasContainer, canvasId) | ||
}) | ||
// Example code of how a grid gallery can be created using PhotoAssistant and how the sorting function can be used. | ||
galleryForm.addEventListener('submit', (event) => { | ||
@@ -64,4 +74,6 @@ event.preventDefault() | ||
// This is optional, call this method first if you wish for the images to be displayed in the grid gallery in alphabetical order (based on the img alt descriptions). | ||
photoAssistant.sortPhotos() | ||
// Display the images in a grid gallery format. | ||
for (let i = 0; i < columnBtns.length; i ++) { | ||
@@ -68,0 +80,0 @@ if (columnBtns[i].checked) { |
@@ -46,3 +46,2 @@ /** | ||
const filterValue = '80%' | ||
const photoFilter = new PhotoFilter() | ||
@@ -59,3 +58,2 @@ | ||
const filterValue = '50%' | ||
const photoFilter = new PhotoFilter() | ||
@@ -62,0 +60,0 @@ |
@@ -9,3 +9,2 @@ /** | ||
const imageDescription = '' | ||
const photoStorage = new PhotoStorage() | ||
@@ -18,3 +17,2 @@ | ||
const imageDescription = null | ||
const photoStorage = new PhotoStorage() | ||
@@ -27,3 +25,2 @@ | ||
const imageDescription = undefined | ||
const photoStorage = new PhotoStorage() | ||
@@ -36,3 +33,2 @@ | ||
const imageDescription = 200 | ||
const photoStorage = new PhotoStorage() | ||
@@ -39,0 +35,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
205
27582177
692