Files
databap/jquery/databap.js
2019-12-08 09:51:19 +01:00

797 lines
22 KiB
JavaScript
Executable File

/* Handling the communication between php processing server and local ajax engine */
/* Databap class */
function Databap()
{
self = this;
//on load init
this.init = function()
{
//Global constants
self.consts.default_hash = self.vars.page_to_hash[self.consts.default_page];
self.consts.process_url = 'index.php';
self.consts.app_image_folder = 'images/';
self.consts.add_code_text = 'Copier le code ici.';
self.consts.search_box_text = 'Recherche...';
self.consts.maxHeight = $(window).innerHeight();
self.consts.maxWidth = $(window).innerWidth();
self.consts.time = (new Date()).getTime();
self.consts.transTime = 200;
//Global variables
self.vars2('tmp', 'object');
self.vars2('loading', 'boolean');
self.vars2('fade', false);
self.vars2('page_cache', 'object');
self.vars2('pageIcon', 'string');
self.vars2('current_page', 'string');
self.vars2('current_user', 'object');
self.vars2('code', 'integer');
self.vars2('id', 0);
self.vars2('phrase', 'string');
self.vars2('code_container', 'string');
self.vars2('focus', true);
self.vars2('disconnected', 'boolean');
self.vars2('mode', 'string');
self.vars2('initLoaded', 'boolean');
self.vars2('chans_list', 'object');
//shortcuts
self.$main = $('#main');
self.$menu = $('#menu');
self.$title = $('#page_title');
self.consts.pageMaxHeight = self.$main.height();
self.consts.pageMaxWidth = self.$main.width();
//Global Events Listeners
self.initSearch();
//Left menu
self.initMenu();
//Events handler
self.resetEventHandlers();
$(document).keyup(function(e){self.onKeyUp(e);});
$(document).keydown(function(e){self.onKeyDown(e);});
$(document).mouseenter(function(){self.onMouveEnter();});
$(document).mouseleave(function(){self.onMouveLeave();});
$(window).unload(function(){self.onQuit();});
//window.onbeforeunload = self.onQuit;
$(window).resize(self.resizeMain).resize();
$(window).bind('hashchange', self.onHashChange);
//Init first page
if(self.hash()=='logout') self.goToInternalLink(self.vars.page_to_hash['welcome']);
else if(self.hash()=='') self.goToInternalLink(self.consts.default_hash, self.consts.default_id); //Fix for old links
else self.onHashChange();
//Load cache
self.loadCache();
};
this.parseHash = function()
{
var sHash = self.hash();
var asHash = sHash.split('-');
var sPage = self.vars.hash_to_page[asHash[0]];
var iItemId = (typeof asHash[1] != 'undefined')?asHash[1]:0;
//var iItemId = (typeof asHash[1] != 'undefined' && !isNaN(asHash[1]))?asHash[1]:0;
//var sItemName = (typeof asHash[1] != 'undefined' && isNaN(asHash[1]))?asHash[1]:'';
return {hash:sHash, page:sPage, id:iItemId/*, name:sItemName*/};
};
this.onHashChange = function(aoOptions)
{
aoOptions = aoOptions || {noFade:false, force:false};
var bNoFade = aoOptions.noFade || false;
var bForce = aoOptions.force || false;
var sDefaultPage = self.vars.current_page==''?'welcome':'error';
var asUrlVars = self.parseHash();
self.switchPage((asUrlVars.hash!='' && typeof asUrlVars.page !== 'undefined')?asUrlVars.page:sDefaultPage, asUrlVars.id, bNoFade, bForce);
};
this.hash = function(hash)
{
if(!hash) return decodeURIComponent(window.location.hash.slice(1));
else
{
window.location.hash = '#'+encodeURIComponent(hash.slice(hash.substr(0, 1)=='#'?1:0));
//favicon, bug firefox
var link = $('link[rel="shortcut icon"]').remove().attr("href");
$('<link href="'+ link +'" rel="shortcut icon" type="image/x-icon" />').appendTo('head');
}
};
//TODO Add images, ...
this.loadCache = function()
{
var iDelay = 1;
for(var i in self.vars.page_to_hash)
{
setTimeout('self.addPageToCache("'+i+'", function(){});', iDelay*60*1000);
iDelay += 1;
}
};
this.vars2 = function(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);
//Get, only name parameter
return getElem(self.vars, asVarName);
};
this.tmp = function(sVarName, oValue)
{
var asVarName = (typeof sVarName == 'object')?sVarName:[sVarName];
asVarName.unshift('tmp');
return self.vars2(asVarName, oValue);
};
this.resetEventHandlers = function()
{
//Reset specific pages event catchers
self.onResize = function(){};
self.resetSize = function(){};
self.onKeyUp = function(e){};
self.onKeyDown = function(e){};
self.onMouveEnter = function(){};
self.onMouveLeave = function(){};
self.onQuit = function(){return true;};
};
this.initSearch = function()
{
$('#form_header').submit(function(event){event.preventDefault();});
var bDirectSearch = (self.vars.current_page=='' && self.parseHash().page=='search' && self.parseHash().id!='');
$('#query')
.addDefaultValue(self.consts.search_box_text, bDirectSearch?self.parseHash().id:'')
.keyup(function(e){if(e.which==13 || e.isTrigger) self.goToInternalLink('search', $('#query').val());});
$('#search_btn_submit').click(function(){$('#query').trigger('keyup');});
};
this.initMenu = function()
{
self.$menu.find('a').each(function(){$(this).attr('title', $(this).find('span').text());});
};
this.setInitEnd = function(bEnded, bAddScrollBar)
{
self.vars.initLoaded = bEnded;
if(self.vars.initLoaded===true)
{
//self.resizeMain();
self.onResize();
//setTimeout(self.onResize, 500);
}
};
this.getMainElem = function(elem)
{
return self.$main.find(elem);
};
//switch to a new page with animation, without processing image
this.switchPage = function(sNextPage, iItemId, bNoFade, bforce)
{
iItemId = iItemId || 0;
bforce = bforce || false;
//FIXME event object instead of string after cancelling page exit. bug ? channeling from parseHash
if(bforce || typeof sNextPage == 'string' && (sNextPage != self.vars.current_page || iItemId!=self.vars.id))
{
//Officially quiting page
var bExit = true;
if(self.vars.current_page!='') bExit = self.onQuit();
if(bExit==false) bExit = confirm('Voulez-vous vraiment quitter la page en cours ?');
if(bExit)
{
//Init's Start
self.setInitEnd(false);
//Reset specific pages event catchers
self.resetEventHandlers();
//Switching data
self.vars.current_page = sNextPage;
self.vars.id = iItemId;
/*if(typeof self.vars.page_cache[sNextPage] == 'undefined')
{
self.vars.loading = true;
$.get
(
self.getPagePath(sNextPage),
function(data)
{
self.vars.loading = false;
self.vars.page_cache[sNextPage] = data;
self.transition(self.switchContent);
}
);
}
else self.transition(self.switchContent);
*/
self.addPageToCache(sNextPage, function(){self.transition(self.switchContent);});
}
//fix the hash
else self.goToInternalLink(self.vars.current_page, self.vars.id);
}
};
this.addPageToCache = function(sPage, fOnSuccess)
{
if(typeof self.vars.page_cache[sPage] == 'undefined')
{
self.vars.loading = true;
$.get
(
self.getPagePath(sPage),
function(data)
{
self.vars.loading = false;
self.vars.page_cache[sPage] = data;
fOnSuccess();
}
);
}
else fOnSuccess();
};
this.transition = function(fOnFinish)
{
if(self.vars2('fade')) $.when(self.$main.add(self.$title).stop().fadeTo(self.consts.transTime, 0)).done(fOnFinish);
else fOnFinish();
self.vars2('fade', false);
};
this.switchContent = function()
{
//Add page Header
self.$title
.find('.side_margins').attr('id', self.vars.current_page+'_title')
.find('#title_text').text(self.vars.page_titles[self.vars.current_page]);
self.$title.fadeTo(self.consts.transTime, 1);
self.vars.pageIcon = 'fa-c-'+self.vars.current_page;
self.pageIcon(self.vars.pageIcon);
//Page replacement
self.$main.empty().fadeTo(self.consts.transTime, 1).append(self.vars.page_cache[self.vars.current_page]);
//Browser tab title
self.setTitle();
//Reset specific page variables
self.vars2('tmp', {});
//Page specific Actions
self.pageInit();
};
this.pageIcon = function(pageIcon, comment)
{
self.$title
.find('h1').attr('title', comment || '')
.find('#page_icon')
.attr('class', 'fa fa-fw fa-20')
.addClass(pageIcon);
};
this.addBufferIcon = function()
{
self.pageIcon('fa-spin fa-c-loading', 'Processing...');
};
this.addSuccessIcon = function()
{
self.pageIcon('fa-c-ok', 'Op&eacute;ration r&eacute;ussie');
setTimeout(self.resetIcon, 2000);
};
this.addFailIcon = function(sMsg)
{
if(!sMsg) sMsg = 'Echec de connexion. Essaie de refresh la page';
self.pageIcon('fa-c-ko', sMsg);
setTimeout(self.resetIcon, 5000);
};
this.resetIcon = function()
{
self.pageIcon(self.vars.pageIcon, '');
};
this.resizeMain = function()
{
//Maximize main div height to fill up the page
var iPageHeight = $('body').outerHeight(true);
var iWindowHeight = $(window).innerHeight();
self.$main.height('+='+(iWindowHeight - iPageHeight));
self.$menu.height($('#main_container').height());
//Update size
self.consts.maxHeight = $(window).innerHeight();
self.consts.maxWidth = $(window).innerWidth();
self.consts.pageMaxHeight = self.$main.innerHeight();
self.consts.pageMaxWidth = self.$main.innerWidth();
//Page event
self.onResize();
self.updateScrollBar();
};
this.maximizeElem = function($Elem, bfitToElemContent, $Box)
{
$Box = $Box || self.$main;
bfitToElemContent = bfitToElemContent || false;
//Maximize to box height
var iDelta = $Box.getEmptyHeight();
//debug('Giving empty '+iDelta+'px (in #'+$Box.attr('id')+') to #'+$Elem.attr('id')+' (originally : '+$Elem.height()+')');
if(iDelta != 0) $Elem.height('+='+iDelta);
//debug('Now, #'+$Elem.attr('id')+' height is '+$Elem.height()+'px');
//Minimize to elem height
if(bfitToElemContent)
{
iDelta = $Elem.getEmptyHeight();
if(iDelta > 0) $Elem.height('-='+iDelta);
//debug('Removing useless '+iDelta+'px from #'+$Elem.attr('id'));
}
};
this.saveForm = function(action, $form, fOnSuccess, bProcessIcon, dataType, asVars)
{
var sFormVars = $form.serialize()+($.isEmptyObject(asVars)?'':'&'+$.param(asVars));
bProcessIcon = bProcessIcon || false;
if(bProcessIcon) self.addBufferIcon();
if(!dataType) dataType = 'text';
self.vars.loading = true;
$.ajax(
{
type: 'POST',
url: self.getActionLink(action),
data: sFormVars,
dataType: dataType
})
.done(function(result)
{
self.vars.loading = false;
self.vars.disconnected = false;
if(bProcessIcon) self.resetIcon();
fOnSuccess(result);
})
.fail(function(jqXHR, textStatus, errorThrown)
{
self.vars.loading = false;
self.vars.disconnected = true;
debug('Error databap.js 331');
self.showError(textStatus);
});
};
this.getInfo = function(action, fOnSuccess, vars, type, fOnError, bProcessIcon)
{
if(!vars) vars = {};
if(!type) type = 'html';
bProcessIcon = bProcessIcon || false;
if(bProcessIcon) self.addBufferIcon();
vars['a'] = action;
self.vars.loading = true;
$.ajax(
{
url: self.consts.process_url,
data: vars,
dataType: type
})
.done(function(result)
{
//TODO use result.result and result.desc, make it standard
if(result==self.consts.errors.disconnected) databap.refresh();
else if((result==self.consts.error || typeof result.success != 'undefined' && result.success==self.consts.error) && typeof fOnError !== 'undefined') fOnError();
else
{
self.vars.loading = false;
self.vars.disconnected = false;
if(bProcessIcon) self.resetIcon();
fOnSuccess(result);
}
})
.fail(function(jqXHR, textStatus, errorThrown)
{
if(jqXHR.responseText==self.consts.errors.disconnected) databap.refresh();
self.vars.loading = false;
self.vars.disconnected = true;
debug('Error databap.js 361');
if(bProcessIcon) self.resetIcon();
if(!fOnError)
{
self.showError(textStatus);
debug(textStatus+' '+errorThrown);
}
else fOnError(textStatus);
});
};
this.getSyncInfo = function(action, vars)
{
if(!vars) vars = {};
vars['a'] = action;
return $.ajax
(
{
url: self.consts.process_url,
type: "GET",
data: vars,
dataType: "html",
async: false,
success: function(r){/*debug('getSyncInfo: Ok');*/}
}
).responseText;
};
this.showError = function(textStatus)
{
//debug('ERROR : '+textStatus);
self.addFailIcon();
};
this.getUserInfo = function(fOnSuccess)
{
if(typeof self.vars.current_user.name == 'undefined')
{
self.getInfo
(
'user_info',
function(user)
{
self.vars.current_user = user;
fOnSuccess(user);
},
{},
'json'
);
}
else fOnSuccess(self.vars.current_user);
};
this.appendItem = function(asItemInfo, $Container, $bAnimation)
{
//Filling up the item line
var $verHtml = $(self.consts.versionHtml);
$verHtml.find('#description').html(asItemInfo.title);
$verHtml.find('#author_name').html(asItemInfo.name);
$verHtml.find('#author_company').html(asItemInfo.company);
$verHtml.find('#led').html(asItemInfo.led);
//Rank (search)
if(typeof asItemInfo.rank != 'undefined')
{
$verHtml.find('.glue-right')
.append(
$('<span>', {'class':'rank'})
.append($('<i>', {'class':'fa fa-inline fa-c-kpi'}))
.append(asItemInfo.rank)
);
}
//Icon
$verHtml.find('#type_logo').addClass('fa-c-'+asItemInfo.type);
//Link
var sItemLink = self.getInternalLink(asItemInfo.type, asItemInfo.id_item);
$verHtml.find('#item_link').attr('href', sItemLink).attr('title', 'Lien vers '+sItemLink);
$verHtml = self.setElemTags($verHtml, asItemInfo.id_item, false, asItemInfo.type);
//Display
$bAnimation = (typeof $bAnimation != 'undefined')?$bAnimation:true;
var $Container = self.getMainElem('#list_container');
if($bAnimation) $verHtml.hide().appendTo($Container).slideDown('fast');
else $verHtml.appendTo($Container);
};
this.getActionLink = function(sAction, oVars)
{
if(!oVars) oVars = {};
sVars = '';
for(i in oVars)
{
sVars += '&'+i+'='+oVars[i];
}
return self.consts.process_url+'?a='+sAction+sVars;
};
this.getInternalLink = function(sPage, iItemId, bAbsolute)
{
bAbsolute = bAbsolute || false;
if(sPage.length==1) sPage = self.vars.hash_to_page[sPage]; //if hash is provided instead of page
return (bAbsolute?self.vars.serv_name:'')+'#'+sPage+((iItemId>0 || iItemId!='')?'-'+escape($.trim(iItemId)):'');
};
this.goToInternalLink = function(sPage, iItemId, bFade)
{
self.vars2('fade', bFade || false);
iItemId = iItemId || 0;
var sHash = self.getInternalLink(sPage, iItemId).substr(1);
if(sHash==self.hash()) self.onHashChange({force:true});
else self.hash(sHash);
};
this.refresh = function()
{
self.tmp("refresh", true);
//self.goToInternalLink(databap.vars.current_page, databap.vars.id);
location.reload(true);
};
this.goToExternalLink = function(sUrl)
{
window.location = sUrl;
};
this.appendCode = function(codeBox, info)
{
self.vars.id = info.id_code;
self.vars.phrase = (!info.phrase)?info.id_code:info.phrase;
//#code_reader
$codeBox = self.setElemTags($(codeBox), [self.vars.id]);
//About code
self.getMainElem('#'+self.getElemTag('code_lines', self.vars.id)).html(info.code);
self.getMainElem('#'+self.getElemTag('description', self.vars.id)).html(info.description);
//About author
self.getMainElem('#'+self.getElemTag('author_name', self.vars.id)).text(info.name);
self.getMainElem('#'+self.getElemTag('author_company', self.vars.id)).text(info.company);
self.getMainElem('#'+self.getElemTag('led', self.vars.id)).text(info.led);
self.getMainElem('#'+self.getElemTag('item_link', self.vars.id))
.prop('href', self.getInternalLink('code', info.id_code))
.find('.fa').addClass('fa-c-code');
};
this.setElemTags = function($CodeBox, aiIds, bUpdate, sType)
{
self.setElemTag($CodeBox, aiIds, bUpdate, sType);
$CodeBox.find('[id]').each(function(){self.setElemTag($(this), aiIds, bUpdate, sType);});
return $CodeBox;
};
this.setElemTag = function($Tag, aiIds, bUpdate, sType)
{
var sCurTagId = $Tag.attr('id');
//Replace only ids existing in aiIds, keep the others
if(bUpdate)
{
var aiCurTagIds = self.getElemIds(sCurTagId);
for(i in aiIds)
{
aiCurTagIds[i] = aiIds[i];
}
aiIds = aiCurTagIds;
}
var sNewTagId = self.getElemTag(self.stripElemIds(sCurTagId), aiIds, sType);
$Tag.attr('id', sNewTagId);
if($Tag.attr('name') != undefined) $Tag.attr('name', sNewTagId);
};
this.getElemTag = function(sTag, aiIds, sType)
{
if(!sType) sType = 'c';
if(typeof aiIds != 'object') aiIds = [aiIds];
return sType+implode(self.consts.id_sep, aiIds)+self.consts.id_sep+sTag;
};
this.getFirstElemId = function(sTag)
{
var aiIds = self.getElemIds(sTag);
return aiIds[0];
};
this.getElemIds = function(sTag)
{
return array_filter(explode(self.consts.id_sep, sTag.substr(1)), isNumeric);
};
this.stripElemIds = function(sTag)
{
//var sPattern = 'c\\d+'+self.consts.id_sep;
var sType = sTag.substr(0, 1);
var sPattern = self.getElemTag('', '\\d+', sType);
if(self.checkRegExMatch(sPattern, sTag))
{
sTag = sTag.substr(self.getElemTag('', self.getElemIds(sTag), sType).length);
}
return sTag;
};
this.checkRegExMatch = function(sPattern, sText)
{
var oRegEx = new RegExp(sPattern, 'i');
return sText.match(oRegEx);
};
this.setCodeContainer = function(fOnSuccess, containerId)
{
if(typeof self.vars.code_container === 'undefined' || self.vars.code_container == '')
{
self.getInfo
(
'code_block',
function(code_block)
{
self.vars.code_container = code_block;
if(containerId) self.appendContainer(containerId);
fOnSuccess();
}
);
}
else
{
if(containerId) self.appendContainer(containerId);
fOnSuccess();
}
};
this.appendContainer = function(containerId, codeId)
{
if(containerId != '')
{
if(!codeId)
{
codeBoxId = 'code_reader';
container = self.vars.code_container;
}
else
{
codeBoxId = self.getElemTag('code_reader', codeId);
container = self.vars.code_container.replace('id="code_reader"', 'id="'+codeBoxId+'"');
}
self.getMainElem(containerId).append(container);
return codeBoxId;
}
else
{
return false;
}
};
this.getImagePath = function(imageName)
{
return 'url("'+self.consts.app_image_folder+imageName+'")';
};
this.getPagePath = function(sPageName)
{
return self.consts.mask_folder+sPageName+'.html?'+self.consts.time;
};
this.addPunctuation = function(sMsg)
{
var asPunctuations = ['?', '!', '.', ',', ':', ';', '-', '/'];
return sMsg+($.inArray(sMsg.slice(-1), asPunctuations)==-1?'.':'');
};
this.addErrorBefore = function(msg, elem)
{
self.addMsgBefore(this.addPunctuation(msg), 'error', elem);
};
this.addWarningBefore = function(msg, elem)
{
msg = 'Attention : '+this.addPunctuation(msg);
self.addMsgBefore(msg, 'warning', elem);
};
this.addSuccessBefore = function(msg, elem)
{
self.addMsgBefore(this.addPunctuation(msg), 'success', elem);
};
this.addMsgBefore = function(msg, msgClass, elem)
{
var $msg = $('<p>', {'class':msgClass}).append($('<i>', {'class':'fa fa-inline fa-c-'+msgClass})).append(msg);
$msg.hide().insertBefore(elem).slideDown('fast', function(){databap.updateScrollBar('bottom');}).delay(5000).slideUp('fast', function(){$(this).remove();databap.updateScrollBar();});
};
this.feedback = function(sClass, sMsg, bClean)
{
bClean = bClean || false;
if(sClass=='error' && sMsg=='') sMsg = 'Aïe ! Une erreur inconnue est suvenue';
else if(sClass=='error' && $.inArray(sMsg, self.consts.errors.system)!=-1) sMsg = 'Une erreur interne est survenue. Merci de contacter l\'admin';
if(sClass==self.consts.error) sClass = 'error';
if(sClass==self.consts.success) sClass = 'success';
//clean box
$Box = $('#title_feedback');
if(bClean) $Box.empty();
$('<span>', {'class':'feedback '+sClass})
.append($('<i>', {'class':'fa fa-inline fa-c-'+sClass}))
.append(self.addPunctuation(sMsg))
.appendTo($Box)
.slideDown('fast')
.delay(5000)
.slideUp('fast', function(){$(this).remove();});
};
this.setTitle = function(extra)
{
extra = extra || '';
if(extra!='') extra += ' | ';
var page = self.vars.page_titles[self.vars.current_page];
if(self.vars.id) page += ' '+self.vars.id;
document.title = extra+'Databap '+chr('8226')+' '+page;
};
this.initScrollBar = function(sBox, sSubBox, sContent)
{
self.tmp('scrollbar', {}); //TODO in page switch
$(sSubBox)
.before('<div class="scrollbar"><div class="track round"><div class="thumb round clickable"><div class="end round clickable"></div></div></div></div>')
.addClass('scrollbar_box round');
$(sContent).addClass('scrollbar_subbox');
self.tmp('scrollbar', $(sBox).tinyscrollbar({viewport:sSubBox, overview:sContent}));
};
this.setScrollBarSize = function(iBoxSize)
{
if(self.tmp('scrollbar'))
{
var $Box = self.tmp('scrollbar').find('.scrollbar_box');
if(iBoxSize=='optimize') self.maximizeElem($Box, true);
else if(iBoxSize=='maximize') self.maximizeElem($Box, false);
else $Box.height(iBoxSize);
self.updateScrollBar();
}
};
this.updateScrollBar = function(sPos)
{
sPos = sPos || 'relative';
if(self.tmp('scrollbar')) self.tmp('scrollbar').tinyscrollbar_update(sPos);
};
this.isScrollBarAtBottom = function()
{
return self.tmp('scrollbar').tinyscrollbar_isBottom();
};
this.unifyWidth = function($ItemsSet)
{
var iMaxWidth = 0;
$ItemsSet.each(function(){iMaxWidth = Math.max(iMaxWidth, $(this).width());});
$ItemsSet.each(function(){if($(this).width() < iMaxWidth) $(this).width(iMaxWidth);});
};
this.shareEvent = function(sType, iId)
{
if(iId!='')
{
$('#share')
.hide()
.text(self.getInternalLink(sType, iId, true))
.addClass('addr')
.slideDown('fast')
.unbind('click');
}
};
}