Add link on feed items

This commit is contained in:
2020-08-16 22:17:24 +02:00
parent f05cdbf351
commit b40d813634
9 changed files with 128 additions and 52 deletions

View File

@@ -141,6 +141,7 @@ class Spot extends Main
'user' => $this->oUser->getUserInfo() 'user' => $this->oUser->getUserInfo()
), ),
'consts' => array( 'consts' => array(
'server' => $this->asContext['serv_name'],
'geo_server' => Settings::GEO_SERVER, 'geo_server' => Settings::GEO_SERVER,
'modes' => Project::MODES, 'modes' => Project::MODES,
'default_timezone' => Settings::TIMEZONE 'default_timezone' => Settings::TIMEZONE

View File

@@ -42,6 +42,8 @@ media_count = Media $0 / $1
media_no_id = Missing Media ID in request media_no_id = Missing Media ID in request
media_comment_update= Comment of media "$0" updated media_comment_update= Comment of media "$0" updated
see_on_google = See on Google Maps see_on_google = See on Google Maps
copy_to_clipboard = Copy direct link to clipboard
link_copied = Link copied!
city_time = $0 Time city_time = $0 Time

View File

@@ -42,6 +42,8 @@ media_count = Média $0 sur $1
media_no_id = ID du média manquant media_no_id = ID du média manquant
media_comment_update= Commentaire du media "$0" mis-à-jour media_comment_update= Commentaire du media "$0" mis-à-jour
see_on_google = Voir la position sur Google Maps see_on_google = Voir la position sur Google Maps
copy_to_clipboard = Copie le lien dans le presse-papier
link_copied = Lien copié !
city_time = heure de $0 city_time = heure de $0

View File

@@ -739,7 +739,7 @@ function focusOnPost(oFocusPost) {
var $Post = oSpot.tmp('$PostList').find(sElemId); var $Post = oSpot.tmp('$PostList').find(sElemId);
var bGetToTop = (oSpot.tmp('$PostList').height() - (($Post.length > 0)?$Post.position().top:0) >= $(window).height()); var bGetToTop = (oSpot.tmp('$PostList').height() - (($Post.length > 0)?$Post.position().top:0) >= $(window).height());
if($Post.length > 0 && (bGetToTop || self.tmp('out-of-data'))) { if($Post.length > 0 && (bGetToTop || self.tmp('out-of-data'))) {
self.tmp('simple-bar').getScrollElement().scrollTop = $Post.position().top + self.tmp('$Poster').outerHeight(true); self.tmp('simple-bar').getScrollElement().scrollTop = $Post.position().top + parseInt($Post.css('margin-top')) + self.tmp('$Poster').outerHeight(true);
if(oFocusPost.type=='media' || oFocusPost.type=='message') $Post.find('a.drill').click(); if(oFocusPost.type=='media' || oFocusPost.type=='message') $Post.find('a.drill').click();
} }
else if(!self.tmp('out-of-data')) updateFeed(false, false, function() {focusOnPost(oFocusPost);}); else if(!self.tmp('out-of-data')) updateFeed(false, false, function() {focusOnPost(oFocusPost);});
@@ -758,6 +758,9 @@ function setFeedUpdateTimer(iSeconds, fCallback) {
function getPost(asPost) { function getPost(asPost) {
asPost.headerless = asPost.headerless || false; asPost.headerless = asPost.headerless || false;
var bLink = false;
var asHash = oSpot.getHash();
var sHash = '#'+[asHash.page, asHash.items[0], asPost.type, asPost.id].join(self.consts.hash_sep);
var $Post = $('<div>', {'class':'post-item '+asPost.type+(asPost.headerless?' headerless':'')}); var $Post = $('<div>', {'class':'post-item '+asPost.type+(asPost.headerless?' headerless':'')});
if(asPost.id) $Post.prop('id', asPost.type+'-'+asPost.id); if(asPost.id) $Post.prop('id', asPost.type+'-'+asPost.id);
@@ -769,6 +772,7 @@ function getPost(asPost) {
switch(asPost.type) { switch(asPost.type) {
case 'message': case 'message':
bLink = true;
$Body = $('<div>', {'class':'body-box'}) $Body = $('<div>', {'class':'body-box'})
.data('id', asPost.id_message) .data('id', asPost.id_message)
.data('clicked', false) .data('clicked', false)
@@ -811,10 +815,12 @@ function getPost(asPost) {
); );
break; break;
case 'media': case 'media':
bLink = true;
$Body = $('<div>', {'class':'body-box'}).append(getMediaLink(asPost, 'post')); $Body = $('<div>', {'class':'body-box'}).append(getMediaLink(asPost, 'post'));
if(asPost.comment) $Body.find('a.drill').append($('<span>', {'class':'comment'}).text(asPost.comment)); if(asPost.comment) $Body.find('a.drill').append($('<span>', {'class':'comment'}).text(asPost.comment));
break; break;
case 'post': case 'post':
bLink = true;
$Body = $('<div>') $Body = $('<div>')
.append($('<p>', {'class':'message'}).text(asPost.content)) .append($('<p>', {'class':'message'}).text(asPost.content))
.append($('<p>', {'class':'signature'}).text('-- '+asPost.formatted_name)); .append($('<p>', {'class':'signature'}).text('-- '+asPost.formatted_name));
@@ -832,11 +838,27 @@ function getPost(asPost) {
$Post $Post
.append($('<div>', {'class':'header'}) .append($('<div>', {'class':'header'})
.append($('<span>', {'class':'index'}).addIcon('fa-'+sType)) .append($('<span>', {'class':'index'})
.addIcon('fa-'+sType)
.append(asPost.displayed_id?' '+oSpot.lang('counter', asPost.displayed_id):'')
)
.append($('<span>', {'class':'time'}).hoverSwap(sRelTime, sAbsTime+((self.tmp('site_tz_notice')!='')?' ('+self.tmp('site_tz_notice')+')':'')))) .append($('<span>', {'class':'time'}).hoverSwap(sRelTime, sAbsTime+((self.tmp('site_tz_notice')!='')?' ('+self.tmp('site_tz_notice')+')':''))))
.append($('<div>', {'class':'body'}).append($Body)); .append($('<div>', {'class':'body'}).append($Body));
if(asPost.displayed_id) $Post.find('.index').append(' '+oSpot.lang('counter', asPost.displayed_id)); if(bLink) {
$Post.find('.index').append($('<a>', {'class':'link', 'href':sHash, 'title':oSpot.lang('copy_to_clipboard')})
.data('url', self.consts.server+sHash)
.addIcon('fa-link')
.click(function(){
copyTextToClipboard($(this).data('url'));
$(this).parent().append($('<span>', {'class':'link_copied'})
.text(oSpot.lang('link_copied'))
.delay(5000)
.fadeOut(400, function(){$(this).remove();})
);
})
);
}
return $Post; return $Post;
} }

View File

@@ -6,72 +6,72 @@ function Spot(asGlobals)
this.consts.title = 'Spotty'; this.consts.title = 'Spotty';
this.consts.default_page = 'project'; this.consts.default_page = 'project';
this.consts.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone; this.consts.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone;
/* Initialization */ /* Initialization */
this.init = function() this.init = function()
{ {
//Variables & constants from php //Variables & constants from php
self.vars('tmp', 'object'); self.vars('tmp', 'object');
self.vars('page', 'string'); self.vars('page', 'string');
self.updateVars(asGlobals.vars); self.updateVars(asGlobals.vars);
//page elem //page elem
self.elem = {}; self.elem = {};
self.elem.container = $('#container'); self.elem.container = $('#container');
self.elem.main = $('#main'); self.elem.main = $('#main');
self.resetTmpFunctions(); self.resetTmpFunctions();
//On Key down //On Key down
$('html').on('keydown', function(oEvent){self.onKeydown(oEvent);}); $('html').on('keydown', function(oEvent){self.onKeydown(oEvent);});
//on window resize //on window resize
$(window).on('resize', function(){self.onResize();}); $(window).on('resize', function(){self.onResize();});
//Setup menu //Setup menu
//self.initMenu(); //self.initMenu();
//Hash management //Hash management
$(window) $(window)
.bind('hashchange', self.onHashChange) .bind('hashchange', self.onHashChange)
.trigger('hashchange'); .trigger('hashchange');
}; };
this.updateVars = function(asVars) this.updateVars = function(asVars)
{ {
$.each(asVars, function(sKey, oValue){self.vars(sKey, oValue)}); $.each(asVars, function(sKey, oValue){self.vars(sKey, oValue)});
}; };
/* Variable Management */ /* Variable Management */
this.vars = function(oVarName, oValue) this.vars = function(oVarName, oValue)
{ {
var asVarName = (typeof oVarName == 'object')?oVarName:[oVarName]; var asVarName = (typeof oVarName == 'object')?oVarName:[oVarName];
//Set, name & type / default value (init) //Set, name & type / default value (init)
if(typeof oValue !== 'undefined') setElem(self.vars, copyArray(asVarName), oValue); if(typeof oValue !== 'undefined') setElem(self.vars, copyArray(asVarName), oValue);
//Get, only name parameter //Get, only name parameter
return getElem(self.vars, asVarName); return getElem(self.vars, asVarName);
}; };
this.tmp = function(sVarName, oValue) this.tmp = function(sVarName, oValue)
{ {
var asVarName = (typeof sVarName == 'object')?sVarName:[sVarName]; var asVarName = (typeof sVarName == 'object')?sVarName:[sVarName];
asVarName.unshift('tmp'); asVarName.unshift('tmp');
return self.vars(asVarName, oValue); return self.vars(asVarName, oValue);
}; };
/* Interface with server */ /* Interface with server */
this.get = function(sAction, fOnSuccess, oVars, fOnError, fonProgress) this.get = function(sAction, fOnSuccess, oVars, fOnError, fonProgress)
{ {
if(!oVars) oVars = {}; if(!oVars) oVars = {};
fOnError = fOnError || function(sError) {console.log(sError);}; fOnError = fOnError || function(sError) {console.log(sError);};
fonProgress = fonProgress || function(sState){}; fonProgress = fonProgress || function(sState){};
fonProgress('start'); fonProgress('start');
oVars['a'] = sAction; oVars['a'] = sAction;
oVars['t'] = self.consts.timezone; oVars['t'] = self.consts.timezone;
return $.ajax( return $.ajax(
@@ -84,7 +84,7 @@ function Spot(asGlobals)
{ {
fonProgress('done'); 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, self.consts.lang_prefix.length)==self.consts.lang_prefix) oData.desc = self.lang(oData.desc.substr(5));
if(oData.result==self.consts.error) fOnError(oData.desc); if(oData.result==self.consts.error) fOnError(oData.desc);
else fOnSuccess(oData.data, oData.desc); else fOnSuccess(oData.data, oData.desc);
}) })
@@ -94,31 +94,31 @@ function Spot(asGlobals)
fOnError(textStatus+' '+errorThrown); fOnError(textStatus+' '+errorThrown);
}); });
}; };
this.lang = function(sKey, asParams) { this.lang = function(sKey, asParams) {
var sParamType = $.type(asParams); var sParamType = $.type(asParams);
if(sParamType == 'undefined') asParams = []; if(sParamType == 'undefined') asParams = [];
else if($.type(asParams) != 'array') asParams = [asParams]; else if($.type(asParams) != 'array') asParams = [asParams];
var sLang = ''; var sLang = '';
if(sKey in self.consts.lang) { if(sKey in self.consts.lang) {
sLang = self.consts.lang[sKey]; sLang = self.consts.lang[sKey];
for(i in asParams) sLang = sLang.replace('$'+i, asParams[i]); for(i in asParams) sLang = sLang.replace('$'+i, asParams[i]);
} }
else console.log('missing translation: '+sKey); else console.log('missing translation: '+sKey);
return sLang; return sLang;
}; };
/* Page Switch - Trigger & Event catching */ /* Page Switch - Trigger & Event catching */
this.onHashChange = function() this.onHashChange = function()
{ {
var asHash = self.getHash(); var asHash = self.getHash();
if(asHash.hash !='' && asHash.page != '') self.switchPage(asHash); //page switching if(asHash.hash !='' && asHash.page != '') self.switchPage(asHash); //page switching
else if(self.vars('page')=='') self.setHash(self.consts.default_page); //first page else if(self.vars('page')=='') self.setHash(self.consts.default_page); //first page
}; };
this.getHash = function() this.getHash = function()
{ {
var sHash = self.hash(); var sHash = self.hash();
@@ -126,7 +126,7 @@ function Spot(asGlobals)
var sPage = asHash.shift() || ''; var sPage = asHash.shift() || '';
return {hash:sHash, page:sPage, items:asHash}; return {hash:sHash, page:sPage, items:asHash};
}; };
this.setHash = function(sPage, asItems, bReboot) this.setHash = function(sPage, asItems, bReboot)
{ {
bReboot = bReboot || false; bReboot = bReboot || false;
@@ -139,18 +139,18 @@ function Spot(asGlobals)
self.hash(sPage+sItems, bReboot); self.hash(sPage+sItems, bReboot);
} }
}; };
this.hash = function(hash, bReboot) this.hash = function(hash, bReboot)
{ {
bReboot = bReboot || false; bReboot = bReboot || false;
if(!hash) return window.location.hash.slice(1); if(!hash) return window.location.hash.slice(1);
else window.location.hash = '#'+hash; else window.location.hash = '#'+hash;
if(bReboot) location.reload(); if(bReboot) location.reload();
}; };
/* Page Switch - DOM Replacement */ /* Page Switch - DOM Replacement */
this.getActionLink = function(sAction, oVars) this.getActionLink = function(sAction, oVars)
{ {
if(!oVars) oVars = {}; if(!oVars) oVars = {};
@@ -161,7 +161,7 @@ function Spot(asGlobals)
} }
return self.consts.process_page+'?a='+sAction+sVars; return self.consts.process_page+'?a='+sAction+sVars;
}; };
this.resetTmpFunctions = function() this.resetTmpFunctions = function()
{ {
self.pageInit = function(asHash){console.log('no init for the page: '+asHash.page)}; self.pageInit = function(asHash){console.log('no init for the page: '+asHash.page)};
@@ -171,7 +171,7 @@ function Spot(asGlobals)
self.onFeedback = function(sType, sMsg){}; self.onFeedback = function(sType, sMsg){};
self.onKeydown = function(oEvent){}; self.onKeydown = function(oEvent){};
}; };
this.switchPage = function(asHash) this.switchPage = function(asHash)
{ {
var sPageName = asHash.page; var sPageName = asHash.page;
@@ -180,17 +180,17 @@ function Spot(asGlobals)
{ {
//Delete tmp variables //Delete tmp variables
self.vars('tmp', {}); self.vars('tmp', {});
//disable tmp functions //disable tmp functions
self.resetTmpFunctions(); self.resetTmpFunctions();
//Officially a new page //Officially a new page
var bFirstPage = self.vars('page')==''; var bFirstPage = self.vars('page')=='';
self.vars('page', sPageName); self.vars('page', sPageName);
//Update Page Title //Update Page Title
this.setPageTitle(sPageName+' '+(asHash.items[0] || '')); this.setPageTitle(sPageName+' '+(asHash.items[0] || ''));
//Replacing DOM //Replacing DOM
var $Dom = $(self.consts.pages[sPageName]); var $Dom = $(self.consts.pages[sPageName]);
if(bFirstPage) if(bFirstPage)
@@ -203,11 +203,11 @@ function Spot(asGlobals)
} }
} }
}; };
this.setPageTitle = function(sTitle) { this.setPageTitle = function(sTitle) {
document.title = self.consts.title+' - '+sTitle; document.title = self.consts.title+' - '+sTitle;
}; };
this.splash = function($Dom, asHash, bFirstPage) this.splash = function($Dom, asHash, bFirstPage)
{ {
//Switch main content //Switch main content
@@ -215,7 +215,7 @@ function Spot(asGlobals)
//Page Bootstrap //Page Bootstrap
self.pageInit(asHash, bFirstPage); self.pageInit(asHash, bFirstPage);
//Show main //Show main
var $FadeInElem = bFirstPage?self.elem.container:self.elem.main; var $FadeInElem = bFirstPage?self.elem.container:self.elem.main;
$FadeInElem.hide().fadeTo('slow', 1); $FadeInElem.hide().fadeTo('slow', 1);
@@ -277,7 +277,7 @@ $.prototype.addButton = function(sIcon, sText, sName, fOnClick, sClass)
.addIcon('fa-'+sIcon, (sText != '')) .addIcon('fa-'+sIcon, (sText != ''))
.append(sText) .append(sText)
.click(fOnClick); .click(fOnClick);
return $(this).append($Btn); return $(this).append($Btn);
}; };
@@ -333,13 +333,13 @@ $.prototype.hoverSwap = function(sDefault, sHover)
var $This = $(this), var $This = $(this),
sHover = $This.data('hover'); sHover = $This.data('hover');
sDefault = $This.data('default'); sDefault = $This.data('default');
if(sDefault!='' && sHover != '') { if(sDefault!='' && sHover != '') {
$This.fadeOut('fast', function() { $This.fadeOut('fast', function() {
var $This = $(this); var $This = $(this);
$This.text((sDefault==$This.text())?sHover:sDefault).fadeIn('fast'); $This.text((sDefault==$This.text())?sHover:sDefault).fadeIn('fast');
}); });
} }
}) })
.text(sDefault); .text(sDefault);
}; };
@@ -358,3 +358,35 @@ $.prototype.onSwipe = function(fCallBack){
fCallBack({x:iDeltaX, y:iDeltaY}); fCallBack({x:iDeltaX, y:iDeltaY});
}); });
}; };
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);
}
);
}

View File

@@ -76,6 +76,7 @@ $fa-css-prefix: fa;
.#{$fa-css-prefix}-upload:before { content: fa-content($fa-var-cloud-upload); } .#{$fa-css-prefix}-upload:before { content: fa-content($fa-var-cloud-upload); }
.#{$fa-css-prefix}-video-shot:before { content: fa-content($fa-var-camcorder); } .#{$fa-css-prefix}-video-shot:before { content: fa-content($fa-var-camcorder); }
.#{$fa-css-prefix}-image-shot:before { content: fa-content($fa-var-camera-alt); } .#{$fa-css-prefix}-image-shot:before { content: fa-content($fa-var-camera-alt); }
.#{$fa-css-prefix}-link:before { content: fa-content($fa-var-link); }
/* Feed - Poster */ /* Feed - Poster */
.#{$fa-css-prefix}-poster:before { content: fa-content($fa-var-comment-edit); } .#{$fa-css-prefix}-poster:before { content: fa-content($fa-var-comment-edit); }

View File

@@ -4,13 +4,15 @@ $panel-width: 30%;
$panel-width-max: "400px + 3 * #{$block-spacing}"; $panel-width-max: "400px + 3 * #{$block-spacing}";
//Feed colors //Feed colors
$post-input-bg: #ffffff; //#d9deff; $post-input-bg: #ffffff; //#d9deff;
$post-color: #333; //#323268; $post-color: #333; //#323268;
$post-bg: rgba(255,255,255,.8); //#B4BDFF; $post-color-hover: darken($post-color, 10%);
$message-color: #326526; $post-bg: rgba(255,255,255,.8); //#B4BDFF;
$message-bg: #6DFF58; $message-color: #326526;
$media-color: #333; //#635C28; $message-color-hover: darken($message-color, 10%);
$media-bg: rgba(255,255,255,.8); //#F3EC9F; $message-bg: #6DFF58;
$media-color: #333; //#635C28;
$media-bg: rgba(255,255,255,.8); //#F3EC9F;
//Settings colors //Settings colors
$title-color: $post-color; $title-color: $post-color;
@@ -331,6 +333,13 @@ $legend-color: $post-color;
margin-top: $block-spacing; margin-top: $block-spacing;
} }
a {
color: $post-color;
&:hover {
color: $post-color-hover;
}
}
.message { .message {
margin: 0; margin: 0;
} }
@@ -353,6 +362,10 @@ $legend-color: $post-color;
&.index { &.index {
width: 25%; width: 25%;
.link, .link:visited, .link_copied {
margin-left: 0.5em;
}
} }
&.time { &.time {
@@ -389,6 +402,9 @@ $legend-color: $post-color;
a { a {
color: $message-color; color: $message-color;
&:hover {
color: $message-color-hover;
}
} }
a.drill { a.drill {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long