Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JSDoc annotations and documentation to the JS code #2892

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions assets/js/phoenix_live_view/aria.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
/**
* Utilities for accessibility behaviors and affordances
*/
let ARIA = {
/**
* Focus a main element of the page
*/
focusMain(){
let target = document.querySelector("main h1, main, h1")
if(target){
@@ -9,10 +15,22 @@ let ARIA = {
}
},

/**
* Find the first class in the collection that the given object is an instance of.
* @param {object} instance
* @param {object[]} classes
* @returns {object | null}
*/
anyOf(instance, classes){ return classes.find(name => instance instanceof name) },

/**
* Can the element be focused?
* @param {Element} el
* @param {boolean} [interactiveOnly]
* @returns {boolean}
*/
isFocusable(el, interactiveOnly){
return(
return (
(el instanceof HTMLAnchorElement && el.rel !== "ignore") ||
(el instanceof HTMLAreaElement && el.href !== undefined) ||
(!el.disabled && (this.anyOf(el, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement, HTMLButtonElement]))) ||
@@ -21,11 +39,23 @@ let ARIA = {
)
},

/**
* Focus the given element, reporting the result.
* @param {Element} el
* @param {boolean} [interactiveOnly]
* @returns {boolean} Is the given element now focused?
*/
attemptFocus(el, interactiveOnly){
if(this.isFocusable(el, interactiveOnly)){ try{ el.focus() } catch(e){} }
/* eslint-disable-next-line no-empty */
if(this.isFocusable(el, interactiveOnly)){ try { el.focus() } catch (e){} }
return !!document.activeElement && document.activeElement.isSameNode(el)
},

/**
* Focus the first interactive child element; depth-first search
* @param {Element} el
* @returns {boolean}
*/
focusFirstInteractive(el){
let child = el.firstElementChild
while(child){
@@ -36,6 +66,11 @@ let ARIA = {
}
},

/**
* Focus the first child element; depth-first search
* @param {Element} el
* @returns {boolean} Is the given element now focused?
*/
focusFirst(el){
let child = el.firstElementChild
while(child){
@@ -46,6 +81,11 @@ let ARIA = {
}
},

/**
* Focus the last child; depth-first search
* @param {Element} el
* @returns {boolean} Is the given element now focused?
*/
focusLast(el){
let child = el.lastElementChild
while(child){
@@ -56,4 +96,5 @@ let ARIA = {
}
}
}
export default ARIA

export default ARIA
63 changes: 63 additions & 0 deletions assets/js/phoenix_live_view/browser.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
let Browser = {
/**
* Does browser support pushState feature of the History API?
* @returns {boolean}
*/
canPushState(){ return (typeof (history.pushState) !== "undefined") },

/**
* Remove item from local storage
* @param {Storage} localStorage
* @param {string} namespace
* @param {string} subkey
*/
dropLocal(localStorage, namespace, subkey){
return localStorage.removeItem(this.localKey(namespace, subkey))
},

/**
* Update item in local storage
* @template T
* @param {Storage} localStorage
* @param {string} namespace
* @param {string} subkey
* @param {T} initial - value to set if first save
* @param {(current: T) => T} func - updating function; receives current, JSON-parsed value of store item and saves the JSON-stringified return value;
* @returns {T}
*/
updateLocal(localStorage, namespace, subkey, initial, func){
let current = this.getLocal(localStorage, namespace, subkey)
let key = this.localKey(namespace, subkey)
@@ -13,15 +33,32 @@ let Browser = {
return newVal
},

/**
* Read item from local storage. NOTE: will parse as JSON; might throw
* @param {Storage} localStorage
* @param {string} namespace
* @param {string} subkey
* @returns {any}
*/
getLocal(localStorage, namespace, subkey){
return JSON.parse(localStorage.getItem(this.localKey(namespace, subkey)))
},

/**
* Replace current history state data without navigating
* @param {(currentState: any) => any} callback
*/
updateCurrentState(callback){
if(!this.canPushState()){ return }
history.replaceState(callback(history.state || {}), "", window.location.href)
},

/**
* Perform history state change to URL
* @param {("push"|"replace")} kind
* @param {{type: string, scroll: number|undefined, root: boolean, id: string}} meta
* @param {string} to - URL of destination
*/
pushState(kind, meta, to){
if(this.canPushState()){
if(to !== window.location.href){
@@ -47,21 +84,47 @@ let Browser = {
}
},

/**
* Set document cookie value
* @param {string} name
* @param {string} value
*/
setCookie(name, value){
document.cookie = `${name}=${value}`
},

/**
* Get value from cookie
* @param {string} name
* @returns {string}
*/
getCookie(name){
return document.cookie.replace(new RegExp(`(?:(?:^|.*;\s*)${name}\s*\=\s*([^;]*).*$)|^.*$`), "$1")
},

/**
* Redirect to URL and set flash message if given
* @param {string} toURL
* @param {string} [flash]
*/
redirect(toURL, flash){
if(flash){ Browser.setCookie("__phoenix_flash__", flash + "; max-age=60000; path=/") }
window.location = toURL
},

/**
* Get the namespaced key for use in browser Storage API
* @param {string} namespace
* @param {string} subkey
* @returns {string}
*/
localKey(namespace, subkey){ return `${namespace}-${subkey}` },

/**
* Find element target of the URL hash segment, if it exists
* @param {string} maybeHash
* @returns {HTMLElement|null}
*/
getHashTargetEl(maybeHash){
let hash = maybeHash.toString().substring(1)
if(hash === ""){ return }
2 changes: 1 addition & 1 deletion assets/js/phoenix_live_view/constants.js
Original file line number Diff line number Diff line change
@@ -86,4 +86,4 @@ export const EVENTS = "e"
export const REPLY = "r"
export const TITLE = "t"
export const TEMPLATES = "p"
export const STREAM = "stream"
export const STREAM = "stream"
Loading