', {'class':'save', 'type':'button'})
+ .on('click', (oEvent) => {
+ var $Form = $(oEvent.currentTarget).parent();
+ this.spot.get(
+ 'add_comment',
+ (asData) => {
+ this.addStatus(this.spot.lang('media_comment_update', asData.filename));
+ },
+ {
+ id: $Form.find('.id').val(),
+ content: $Form.find('.content').val()
+ },
+ (sMsgId) => {
+ this.addStatus(this.spot.lang(sMsgId));
+ }
+ );
+ })
+ .text(this.spot.lang('save'))
+ )
+ )
+ )
+ }
+
+ addStatus(sMsg, bClear) {
+ bClear = bClear || false;
+ if(bClear) this.spot.tmp('status-box').empty();
+
+ this.spot.tmp('status-box').append($('').text(sMsg));
+ }
+}
\ No newline at end of file
diff --git a/src/scripts/spot.js b/src/scripts/spot.js
index a9656b9..4812d83 100755
--- a/src/scripts/spot.js
+++ b/src/scripts/spot.js
@@ -1,109 +1,96 @@
-function Spot(asGlobals)
-{
- self = this;
- this.consts = asGlobals.consts;
- this.consts.hash_sep = '-';
- this.consts.title = 'Spotty';
- this.consts.default_page = 'project';
- this.consts.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone;
+export default class Spot {
+
+ constructor(asGlobals) {
+ this.consts = asGlobals.consts;
+ this.consts.hash_sep = '-';
+ this.consts.title = 'Spotty';
+ this.consts.default_page = 'project';
+ this.consts.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone;
+
+ this.pages = {};
+
+ //Variables & constants from php
+ this.vars('tmp', 'object');
+ this.vars('page', 'string');
+ $.each(asGlobals.vars, (sKey, oValue) => {this.vars(sKey, oValue)});
+
+ //page elem
+ this.elem = {};
+ }
/* Initialization */
- this.init = function()
- {
- //Variables & constants from php
- self.vars('tmp', 'object');
- self.vars('page', 'string');
- self.updateVars(asGlobals.vars);
-
- //page elem
- self.elem = {};
- self.elem.container = $('#container');
- self.elem.main = $('#main');
-
- self.resetTmpFunctions();
+ init() {
+ this.elem.container = $('#container');
+ this.elem.main = $('#main');
//On Key down
- $('html').on('keydown', function(oEvent){self.onKeydown(oEvent);});
+ $('html').on('keydown', (oEvent) => {this.onKeydown(oEvent);});
//on window resize
- $(window).on('resize', function(){self.onResize();});
-
- //Setup menu
- //self.initMenu();
+ $(window).on('resize', () => {this.onResize();});
//Hash management
$(window)
- .bind('hashchange', self.onHashChange)
+ .on('hashchange', () => {this.onHashChange();})
.trigger('hashchange');
- };
-
- this.updateVars = function(asVars)
- {
- $.each(asVars, function(sKey, oValue){self.vars(sKey, oValue)});
- };
+ }
/* Variable Management */
- this.vars = function(oVarName, oValue)
- {
+ vars(oVarName, oValue) {
var asVarName = (typeof oVarName == 'object')?oVarName:[oVarName];
//Set, name & type / default value (init)
- if(typeof oValue !== 'undefined') setElem(self.vars, copyArray(asVarName), oValue);
+ if(typeof oValue !== 'undefined') setElem(this.vars, copyArray(asVarName), oValue);
//Get, only name parameter
- return getElem(self.vars, asVarName);
- };
+ return getElem(this.vars, asVarName);
+ }
- this.tmp = function(sVarName, oValue)
- {
+ tmp(sVarName, oValue) {
var asVarName = (typeof sVarName == 'object')?sVarName:[sVarName];
asVarName.unshift('tmp');
- return self.vars(asVarName, oValue);
- };
+ return this.vars(asVarName, oValue);
+ }
/* Interface with server */
- this.get = function(sAction, fOnSuccess, oVars, fOnError, fonProgress)
- {
- if(!oVars) oVars = {};
+ get(sAction, fOnSuccess, oVars, fOnError, fonProgress) {
+ oVars = oVars || {};
fOnError = fOnError || function(sError) {console.log(sError);};
fonProgress = fonProgress || function(sState){};
fonProgress('start');
oVars['a'] = sAction;
- oVars['t'] = self.consts.timezone;
+ oVars['t'] = this.consts.timezone;
return $.ajax(
{
- url: self.consts.process_page,
+ url: this.consts.process_page,
data: oVars,
dataType: 'json'
})
- .done(function(oData)
- {
+ .done((oData) => {
fonProgress('done');
- if(oData.desc.substr(0, self.consts.lang_prefix.length)==self.consts.lang_prefix) oData.desc = self.lang(oData.desc.substr(5));
+ if(oData.desc.substr(0, this.consts.lang_prefix.length)==this.consts.lang_prefix) oData.desc = this.lang(oData.desc.substr(5));
- if(oData.result==self.consts.error) fOnError(oData.desc);
+ if(oData.result==this.consts.error) fOnError(oData.desc);
else fOnSuccess(oData.data, oData.desc);
})
- .fail(function(jqXHR, textStatus, errorThrown)
- {
+ .fail((jqXHR, textStatus, errorThrown) => {
fonProgress('fail');
fOnError(textStatus+' '+errorThrown);
});
- };
+ }
- this.lang = function(sKey, asParams) {
- var sParamType = $.type(asParams);
- if(sParamType == 'undefined') asParams = [];
- else if($.type(asParams) != 'array') asParams = [asParams];
+ lang(sKey, asParams) {
+ asParams = asParams || [];
+ if(typeof asParams == 'string') asParams = [asParams];
+
var sLang = '';
-
- if(sKey in self.consts.lang) {
- sLang = self.consts.lang[sKey];
- for(i in asParams) sLang = sLang.replace('$'+i, asParams[i]);
+ if(sKey in this.consts.lang) {
+ sLang = this.consts.lang[sKey];
+ for(let i in asParams) sLang = sLang.replace('$'+i, asParams[i]);
}
else {
console.log('missing translation: '+sKey);
@@ -111,141 +98,153 @@ function Spot(asGlobals)
}
return sLang;
- };
+ }
/* Page Switch - Trigger & Event catching */
- this.onHashChange = function()
- {
- var asHash = self.getHash();
- if(asHash.hash !='' && asHash.page != '') self.switchPage(asHash); //page switching
- else if(self.vars('page')=='') self.setHash(self.consts.default_page); //first page
- };
+ onHashChange() {
+ var asHash = this.getHash();
+ if(asHash.hash !='' && asHash.page != '') this.switchPage(asHash); //page switching
+ else if(this.vars('page')=='') this.setHash(this.consts.default_page); //first page
+ }
- this.getHash = function()
- {
- var sHash = self.hash();
- var asHash = sHash.split(self.consts.hash_sep);
+ getHash() {
+ var sHash = this.hash();
+ var asHash = sHash.split(this.consts.hash_sep);
var sPage = asHash.shift() || '';
return {hash:sHash, page:sPage, items:asHash};
- };
+ }
- this.setHash = function(sPage, asItems, bReboot)
- {
+ setHash(sPage, asItems, bReboot) {
bReboot = bReboot || false;
sPage = sPage || '';
asItems = asItems || [];
if(typeof asItems == 'string') asItems = [asItems];
- if(sPage != '')
- {
- var sItems = (asItems.length > 0)?self.consts.hash_sep+asItems.join(self.consts.hash_sep):'';
- self.hash(sPage+sItems, bReboot);
- }
- };
- this.hash = function(hash, bReboot)
- {
+ if(sPage != '') {
+ var sItems = (asItems.length > 0)?this.consts.hash_sep+asItems.join(this.consts.hash_sep):'';
+ this.hash(sPage+sItems, bReboot);
+ }
+ }
+
+ hash(hash, bReboot) {
bReboot = bReboot || false;
if(!hash) return window.location.hash.slice(1);
else window.location.hash = '#'+hash;
if(bReboot) location.reload();
- };
+ }
- this.updateHash = function(sType, iId) {
+ updateHash(sType, iId) {
sType = sType || '';
iId = iId || 0;
- var asHash = self.getHash();
- if(iId) self.setHash(asHash.page, [asHash.items[0], sType, iId]);
- };
+ var asHash = this.getHash();
+ if(iId) this.setHash(asHash.page, [asHash.items[0], sType, iId]);
+ }
- this.flushHash = function(asTypes) {
+ flushHash(asTypes) {
asTypes = asTypes || [];
- var asHash = self.getHash();
- if(asHash.items.length > 1 && (asTypes.length == 0 || asTypes.indexOf(asHash.items[1]) != -1)) self.setHash(asHash.page, [asHash.items[0]]);
- };
+ var asHash = this.getHash();
+ if(asHash.items.length > 1 && (asTypes.length == 0 || asTypes.indexOf(asHash.items[1]) != -1)) this.setHash(asHash.page, [asHash.items[0]]);
+ }
+
+ /* Page Events */
+
+ pageInit(asHash) {
+ let sPage = this.vars('page');
+ if(this.pages[sPage].pageInit) this.pages[sPage].pageInit(asHash);
+ else console.log('no init for the page: '+asHash.page);
+ }
+
+ onSamePageMove(asHash) {
+ let sPage = this.vars('page');
+ return (this.pages[sPage] && this.pages[sPage].onSamePageMove)?this.pages[sPage].onSamePageMove(asHash):false;
+ }
+
+ onQuitPage() {
+ let sPage = this.vars('page');
+ return (this.pages[sPage] && this.pages[sPage].onQuitPage)?this.pages[sPage].onQuitPage():true;
+ }
+
+ onResize() {
+ let sPage = this.vars('page');
+ if(this.pages[sPage].onResize) this.pages[sPage].onResize();
+ }
+
+ onFeedback(sType, sMsg, asContext) {
+ asContext = asContext || {};
+ let sPage = this.vars('page');
+ if(this.pages[sPage].onFeedback) this.pages[sPage].onFeedback(sType, sMsg, asContext);
+ }
+
+ onKeydown(oEvent) {
+ let sPage = this.vars('page');
+ if(this.pages[sPage].onKeydown) this.pages[sPage].onKeydown(oEvent);
+ }
/* Page Switch - DOM Replacement */
- this.getActionLink = function(sAction, oVars)
- {
+ getActionLink(sAction, oVars) {
if(!oVars) oVars = {};
- sVars = '';
- for(i in oVars)
- {
- sVars += '&'+i+'='+oVars[i];
- }
- return self.consts.process_page+'?a='+sAction+sVars;
- };
+ let sVars = '';
+
+ for(i in oVars) sVars += '&'+i+'='+oVars[i];
- this.resetTmpFunctions = function()
- {
- self.pageInit = function(asHash){console.log('no init for the page: '+asHash.page)};
- self.onSamePageMove = function(asHash){return false};
- self.onQuitPage = function(){return true};
- self.onResize = function(){};
- self.onFeedback = function(sType, sMsg){};
- self.onKeydown = function(oEvent){};
- };
+ return this.consts.process_page+'?a='+sAction+sVars;
+ }
- this.switchPage = function(asHash)
- {
+ addPage(sPage, oPage) {
+ this.pages[sPage] = oPage;
+ }
+
+ switchPage(asHash) {
var sPageName = asHash.page;
- var bSamePage = (self.vars('page') == sPageName);
- var bFirstPage = (self.vars('page') == '');
+ var bSamePage = (this.vars('page') == sPageName);
+ var bFirstPage = (this.vars('page') == '');
- if(!self.consts.pages[sPageName]) { //Page does not exist
- if(bFirstPage) self.setHash(self.consts.default_page);
- else self.setHash(self.vars('page'), self.vars(['hash', 'items']));
+ if(!this.consts.pages[sPageName]) { //Page does not exist
+ if(bFirstPage) this.setHash(this.consts.default_page);
+ else this.setHash(this.vars('page'), this.vars(['hash', 'items']));
}
- else if(self.onQuitPage(bSamePage) && !bSamePage || self.onSamePageMove(asHash))
+ else if(this.onQuitPage(bSamePage) && !bSamePage || this.onSamePageMove(asHash))
{
//Delete tmp variables
- self.vars('tmp', {});
-
- //disable tmp functions
- self.resetTmpFunctions();
+ this.vars('tmp', {});
//Officially a new page
- self.vars('page', sPageName);
- self.vars('hash', asHash);
-
+ this.vars('page', sPageName);
+ this.vars('hash', asHash);
+
//Update Page Title
this.setPageTitle(sPageName+' '+(asHash.items[0] || ''));
//Replacing DOM
- var $Dom = $(self.consts.pages[sPageName]);
- if(bFirstPage)
- {
- self.splash($Dom, asHash, bFirstPage); //first page
- }
- else
- {
- self.elem.main.stop().fadeTo('fast', 0, function(){self.splash($Dom, asHash, bFirstPage);}); //Switching page
- }
+ var $Dom = $(this.consts.pages[sPageName]);
+ if(bFirstPage) this.splash($Dom, asHash, bFirstPage); //first page
+ else this.elem.main.stop().fadeTo('fast', 0, () => {this.splash($Dom, asHash, bFirstPage);}); //Switching page
}
- else if(bSamePage) self.vars('hash', asHash);
- };
+ else if(bSamePage) this.vars('hash', asHash);
+ }
- this.setPageTitle = function(sTitle) {
- document.title = self.consts.title+' - '+sTitle;
- };
-
- this.splash = function($Dom, asHash, bFirstPage)
+ splash($Dom, asHash, bFirstPage)
{
//Switch main content
- self.elem.main.empty().html($Dom);
+ this.elem.main.empty().html($Dom);
//Page Bootstrap
- self.pageInit(asHash, bFirstPage);
+ this.pageInit(asHash, bFirstPage);
//Show main
- var $FadeInElem = bFirstPage?self.elem.container:self.elem.main;
+ var $FadeInElem = bFirstPage?this.elem.container:this.elem.main;
$FadeInElem.hide().fadeTo('slow', 1);
- };
+ }
- this.getNaturalDuration = function(iHours) {
+ setPageTitle(sTitle) {
+ document.title = this.consts.title+' - '+sTitle;
+ }
+
+ getNaturalDuration(iHours) {
var iTimeMinutes = 0, iTimeHours = 0, iTimeDays = Math.floor(iHours/8); //8 hours a day
if(iTimeDays > 1) iTimeDays = Math.round(iTimeDays * 2) / 2; //Round down to the closest half day
else {
@@ -256,213 +255,13 @@ function Spot(asGlobals)
iTimeMinutes = Math.floor(iHours * 4) * 15; //Round down to the closest 15 minutes
}
return '~ '
- +(iTimeDays>0?(iTimeDays+(iTimeDays%2==0?'':'½')+' '+self.lang(iTimeDays>1?'unit_days':'unit_day')):'') //Days
- +((iTimeHours>0 || iTimeDays==0)?iTimeHours+self.lang('unit_hour'):'') //Hours
+ +(iTimeDays>0?(iTimeDays+(iTimeDays%2==0?'':'½')+' '+this.lang(iTimeDays>1?'unit_days':'unit_day')):'') //Days
+ +((iTimeHours>0 || iTimeDays==0)?iTimeHours+this.lang('unit_hour'):'') //Hours
+((iTimeDays>0 || iTimeMinutes==0)?'':iTimeMinutes) //Minutes
- };
-
- this.checkClearance = function(sClearance) {
- return (self.vars(['user', 'clearance']) >= sClearance);
- };
-}
-
-/* Common Functions */
-
-function copyArray(asArray)
-{
- return asArray.slice(0); //trick to copy array
-}
-
-function getElem(aoAnchor, asPath)
-{
- return (typeof asPath == 'object' && asPath.length > 1)?getElem(aoAnchor[asPath.shift()], asPath):aoAnchor[(typeof asPath == 'object')?asPath.shift():asPath];
-}
-
-function setElem(aoAnchor, asPath, oValue)
-{
- var asTypes = {boolean:false, string:'', integer:0, int:0, array:[], object:{}};
- if(typeof asPath == 'object' && asPath.length > 1)
- {
- var nextlevel = asPath.shift();
- if(!(nextlevel in aoAnchor)) aoAnchor[nextlevel] = {}; //Creating a new level
- if(typeof aoAnchor[nextlevel] !== 'object') debug('Error - setElem() : Already existing path at level "'+nextlevel+'". Cancelling setElem() action');
- return setElem(aoAnchor[nextlevel], asPath, oValue);
}
- else
- {
- var sKey = (typeof asPath == 'object')?asPath.shift():asPath;
- return aoAnchor[sKey] = (!(sKey in aoAnchor) && (oValue in asTypes))?asTypes[oValue]:oValue;
+
+ checkClearance(sClearance) {
+ return (this.vars(['user', 'clearance']) >= sClearance);
}
-}
-
-$.prototype.addInput = function(sType, sName, sValue, aoEvents)
-{
- aoEvents = aoEvents || [];
- var $Input = $(' ', {type: sType, name: sName, value: sValue}).data('old_value', sValue);
- $.each(aoEvents, function(iIndex, aoEvent) {
- $Input.on(aoEvent.on, aoEvent.callback);
- });
- return $(this).append($Input);
-};
-
-$.prototype.addButton = function(sIcon, sText, sName, fOnClick, sClass)
-{
- sText = sText || '';
- sClass = sClass || '';
- var $Btn = $('', {name: sName, 'class':sClass})
- .addIcon('fa-'+sIcon, (sText != ''))
- .append(sText)
- .click(fOnClick);
-
- return $(this).append($Btn);
-};
-
-$.prototype.addIcon = function(sIcon, bMargin, sStyle)
-{
- bMargin = bMargin || false;
- sStyle = sStyle || '';
- return $(this).append($('', {'class':'fa'+sStyle+' '+sIcon+(bMargin?' push':'')}));
-};
-
-$.prototype.defaultVal = function(sDefaultValue)
-{
- $(this)
- .data('default_value', sDefaultValue)
- .val(sDefaultValue)
- .addClass('defaultText')
- .focus(function()
- {
- var $This = $(this);
- if($This.val() == $This.data('default_value')) $This.val('').removeClass('defaultText');
- })
- .blur(function()
- {
- var $This = $(this);
- if($This.val() == '') $This.val($This.data('default_value')).addClass('defaultText');
- });
-};
-
-$.prototype.checkForm = function(sSelector)
-{
- sSelector = sSelector || 'input[type="text"], textarea';
- var $This = $(this);
- var bOk = true;
- $This.find(sSelector).each(function()
- {
- $This = $(this);
- bOk = bOk && $This.val()!='' && $This.val()!=$This.data('default_value');
- });
- return bOk;
-};
-
-$.prototype.cascadingDown = function(sDuration)
-{
- return $(this).slideDown(sDuration, function(){$(this).next().cascadingDown(sDuration);});
-};
-
-$.prototype.hoverSwap = function(sDefault, sHover)
-{
- return $(this)
- .data('default', sDefault)
- .data('hover', sHover)
- .hover(function(){
- var $This = $(this),
- sHover = $This.data('hover');
- sDefault = $This.data('default');
-
- if(sDefault!='' && sHover != '') {
- $This.fadeOut('fast', function() {
- var $This = $(this);
- $This.text((sDefault==$This.text())?sHover:sDefault).fadeIn('fast');
- });
- }
- })
- .text(sDefault);
-};
-
-$.prototype.onSwipe = function(fOnStart, fOnMove, fOnEnd){
- return $(this)
- .on('dragstart', (e) => {
- e.preventDefault();
- })
- .on('mousedown touchstart', (e) => {
- var $This = $(this);
- var oPos = getDragPosition(e);
- $This.data('x-start', oPos.x);
- $This.data('y-start', oPos.y);
- $This.data('x-move', oPos.x);
- $This.data('y-move', oPos.y);
- $This.data('moving', true).addClass('moving');
- fOnStart({
- xStart: $This.data('x-start'),
- yStart: $This.data('y-start')
- });
- })
- .on('touchmove mousemove', (e) => {
- var $This = $(this);
- if($This.data('moving')) {
- var oPos = getDragPosition(e);
- $This.data('x-move', oPos.x);
- $This.data('y-move', oPos.y);
- fOnMove({
- xStart: $This.data('x-start'),
- yStart: $This.data('y-start'),
- xMove: $This.data('x-move'),
- yMove: $This.data('y-move')
- });
- }
- })
- .on('mouseup mouseleave touchend', (e) => {
- var $This = $(this);
- if($This.data('moving')) {
- $This.data('moving', false).removeClass('moving');
- fOnEnd({
- xStart: $This.data('x-start'),
- yStart: $This.data('y-start'),
- xEnd: $This.data('x-move'),
- yEnd: $This.data('y-move')
- });
- }
- });
-};
-
-function getDragPosition(oEvent) {
- let bMouse = oEvent.type.includes('mouse');
- return {
- x: bMouse?oEvent.pageX:oEvent.touches[0].clientX,
- y: bMouse?oEvent.pageY:oEvent.touches[0].clientY
- };
-}
-
-function copyTextToClipboard(text) {
- if(!navigator.clipboard) {
- var textArea = document.createElement('textarea');
- textArea.value = text;
-
- // Avoid scrolling to bottom
- textArea.style.top = '0';
- textArea.style.left = '0';
- textArea.style.position = 'fixed';
-
- document.body.appendChild(textArea);
- textArea.focus();
- textArea.select();
-
- try {
- var successful = document.execCommand('copy');
- if(!successful) console.error('Fallback: Oops, unable to copy', text);
- } catch (err) {
- console.error('Fallback: Oops, unable to copy', err);
- }
-
- document.body.removeChild(textArea);
- return;
- }
- navigator.clipboard.writeText(text).then(
- function() {},
- function(err) {
- console.error('Async: Could not copy text: ', err);
- }
- );
-}
+}
\ No newline at end of file