Skip to content

Commit

Permalink
Joomla popup docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Fedik committed Mar 12, 2023
1 parent e4d87bf commit ac66242
Showing 1 changed file with 168 additions and 64 deletions.
232 changes: 168 additions & 64 deletions build/media_source/system/js/joomla-popup.w-c.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,90 @@
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

// Default template for the popup
const popupTemplate = `<div class="joomla-popup-container">
<header class="joomla-popup-header"></header>
<section class="joomla-popup-body"></section>
<footer class="joomla-popup-footer"></footer>
</div>`;

/**
* JoomlaPopup class implementation for <joomla-popup> element
*/
class JoomlaPopup extends HTMLElement {
/**
* The popup type, supported: inline, iframe, image, ajax.
* @type {string}
*/
popupType = 'inline';
popupHeader = '';

/**
* An optional text for header.
* @type {string}
*/
textHeader = '';

/**
* An optional text for close button. Applied when no Buttons provided.
* @type {string}
*/
textClose = 'Close';

/**
* Content string (html) for inline type popup.
* @type {string}
*/
popupContent = '';

/**
* Source path for iframe, image, ajax.
* @type {string}
*/
src = '';
popupTemplate = popupTemplate;

/**
* An optional list of buttons, to be rendered in footer, or bottom of the popup body.
* Example:
* [{label: 'Yes', onClick: () => popup.close()},
* {label: 'No', onClick: () => popup.close(), className: 'btn btn-danger'}]
* @type {[]}
*/
popupButtons = [];

/**
* An optional limit for the popup width, any valid CSS value.
* @type {string}
*/
width = '';

/**
* An optional height for the popup, any valid CSS value.
* @type {string}
*/
height = '';
textClose = 'Close';

/**
* A template for the popup
* @type {string|HTMLTemplateElement}
*/
popupTemplate = popupTemplate;

connectedCallback() {
this.renderLayout();
}

/**
* Render a main layout, based on given template.
* @returns {JoomlaPopup}
*/
renderLayout() {
if (this.dialog) return this;

// Check for existing layout
if (this.firstElementChild && this.firstElementChild.nodeName === 'DIALOG') {
this.dialog = this.firstElementChild;
this.popupTmplB = this.querySelector('.joomla-popup-body');
this.popupTmplB = this.querySelector('.joomla-popup-body') || this.dialog;
this.popupContentElement = this.popupTmplB;
return this;
}

Expand Down Expand Up @@ -59,69 +115,14 @@ class JoomlaPopup extends HTMLElement {
}

// Set the header
if (this.popupTmplH && this.popupHeader) {
if (this.popupTmplH && this.textHeader) {
const h = document.createElement('h3');
h.insertAdjacentHTML('afterbegin', this.popupHeader);
h.insertAdjacentHTML('afterbegin', this.textHeader);
this.popupTmplH.insertAdjacentElement('afterbegin', h);
}

// Set the body
switch (this.popupType) {
case 'inline':
this.popupTmplB.insertAdjacentHTML('afterbegin', this.popupContent);
this.popupContentElement = this.popupTmplB;
break;
case 'iframe':
const frame = document.createElement('iframe');
const onFrameLoad = () => {
this.classList.add('loaded');
this.classList.remove('loading');
frame.removeEventListener('load', onFrameLoad);
}
frame.addEventListener('load', onFrameLoad);
this.classList.add('loading');
frame.src = this.src;
frame.style.width = '100%';
frame.style.height = '100%';
this.popupContentElement = frame;
this.popupTmplB.appendChild(frame);
break;
case 'image':
const img = document.createElement('img');
const onImgLoad = () => {
this.classList.add('loaded');
this.classList.remove('loading');
img.removeEventListener('load', onImgLoad);
}
img.addEventListener('load', onImgLoad);
this.classList.add('loading');
img.src = this.src;
this.popupContentElement = img;
this.popupTmplB.appendChild(img);
break;
case 'ajax':
this.classList.add('loading');
fetch(this.src)
.then((response) => {
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.text();
}).then((text) => {
this.popupTmplB.insertAdjacentHTML('afterbegin', text);
this.popupContentElement = this.popupTmplB;
this.classList.add('loaded');
this.classList.remove('loading');
}).catch((error) => {
this.classList.add('loaded');
this.classList.remove('loading');
throw error;
});
break;
default:
throw new Error('Unknown popup type requested');
}

this.renderBodyContent();
this.setAttribute('type', this.popupType);

// Create buttons if any
Expand Down Expand Up @@ -170,38 +171,128 @@ class JoomlaPopup extends HTMLElement {
this.dialog.style.height = this.height;
}

console.log(this)
return this;
}

/**
* Render the body content, based on popupType.
* @returns {JoomlaPopup}
*/
renderBodyContent() {
if (!this.popupTmplB || this.popupContentElement) return this;

// Callback for loaded content event listener
const onLoad = () => {
this.classList.add('loaded');
this.classList.remove('loading');
this.popupContentElement.removeEventListener('load', onLoad);
}

this.classList.add('loading');

switch (this.popupType) {
// Create an Inline content
case 'inline':
this.popupTmplB.insertAdjacentHTML('afterbegin', this.popupContent);
this.popupContentElement = this.popupTmplB;
onLoad();
break;

// Create an IFrame content
case 'iframe':
const frame = document.createElement('iframe');
frame.addEventListener('load', onLoad);
frame.src = this.src;
frame.style.width = '100%';
frame.style.height = '100%';
this.popupContentElement = frame;
this.popupTmplB.appendChild(frame);
break;

// Create an Image content
case 'image':
const img = document.createElement('img');
img.addEventListener('load', onLoad);
img.src = this.src;
this.popupContentElement = img;
this.popupTmplB.appendChild(img);
break;

// Create an AJAX content
case 'ajax':
fetch(this.src)
.then((response) => {
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.text();
}).then((text) => {
this.popupTmplB.insertAdjacentHTML('afterbegin', text);
this.popupContentElement = this.popupTmplB;
onLoad();
}).catch((error) => {
throw error;
});
break;
default:
throw new Error('Unknown popup type requested');
}

return this;
}

/**
* Return the popup body element.
* @returns {HTMLElement}
*/
getBody() {
this.renderLayout();

return this.popupTmplB;
}

/**
* Return the popup content element, or body for inline and ajax types.
* @returns {HTMLElement}
*/
getBodyContent() {
this.renderLayout();

return this.popupContentElement || this.popupTmplB;
}

/**
* Open the popup as modal window.
* Will append the element to Document body if not appended before.
*
* @returns {JoomlaPopup}
*/
show(){
if (!this.parentElement) {
document.body.appendChild(this);
}

this.dialog.showModal();
return this;
}

/**
* Closes the popup
*
* @returns {JoomlaPopup}
*/
close() {
if (!this.dialog) {
throw new Error('Calling close for non opened dialog is discouraged.');
}

this.dialog.close();
return this;
}

/**
* Destroys the popup.
*/
destroy() {
if (this.dialog) {
this.dialog.close();
Expand All @@ -215,6 +306,11 @@ class JoomlaPopup extends HTMLElement {
this.popupContentElement = null;
}

/**
* Helper method to show an Alert.
* @param {String} message
* @returns {JoomlaPopup}
*/
static alert(message){
const popup = new this;
popup.popupType = 'inline';
Expand All @@ -226,6 +322,14 @@ class JoomlaPopup extends HTMLElement {
return popup;
}

/**
* Helper method to show a Confirmation popup.
*
* @param {String} message
* @param {Callback} onAccept
* @param {Callback} onReject
* @returns {JoomlaPopup}
*/
static confirm(message, onAccept, onReject){
const popup = new this;
popup.popupType = 'inline';
Expand Down Expand Up @@ -255,7 +359,7 @@ export { JoomlaPopup };

// ================= testing ======================= //
const popup = new JoomlaPopup;
popup.popupHeader = 'The header';
popup.textHeader = 'The header';
popup.popupContent = '<strong>blabla very strong text</strong>';

// popup.popupType = 'iframe';
Expand Down

0 comments on commit ac66242

Please sign in to comment.