266 lines
17 KiB
JavaScript
266 lines
17 KiB
JavaScript
// ==UserScript==
|
|
// @name GaiaGps Track Colors Mass Updater
|
|
// @description Add missing feature: Mass update of GaiaGps Track Colors
|
|
// @version 1.1
|
|
// @grant none
|
|
// @match https://www.gaiagps.com/datasummary/tracks/
|
|
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.5.0/jquery.min.js
|
|
// @namespace https://greasyfork.org/users/583371
|
|
// ==/UserScript==
|
|
|
|
console.log('computes');
|
|
|
|
function init() {
|
|
$Selector = $('<div class="MuiPaper-root MuiMenu-paper MuiPopover-paper MuiPaper-elevation8 MuiPaper-rounded" style="opacity: 1; transform: none; min-width: 40px; transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 67ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; top: 440px; left: 114px; transform-origin: 0px 0px 0px;" tabindex="-1"><ul class="MuiList-root MuiMenu-list MuiList-padding" role="listbox" tabindex="-1" style="display: flex; flex-wrap: wrap; width: 217px; flex-grow: 1; justify-content: center;"><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#FFEF00" data-value="#FFEF00"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(255, 239, 0); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#A4A4A4" data-value="#A4A4A4"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(164, 164, 164); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#000000" data-value="#000000"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(0, 0, 0); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#BAF200" data-value="#BAF200"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(186, 242, 0); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#FFC900" data-value="#FFC900"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(255, 201, 0); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#7AD915" data-value="#7AD915"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(122, 217, 21); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#784D3E" data-value="#784D3E"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(120, 77, 62); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#F42410" data-value="#F42410"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(244, 36, 16); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#E834EC" data-value="#E834EC"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(232, 52, 236); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#A726BC" data-value="#A726BC"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(167, 38, 188); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#5726C2" data-value="#5726C2"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(87, 38, 194); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root Mui-selected MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button Mui-selected" tabindex="0" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#2D3FC7" aria-selected="true" data-value="#2D3FC7"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(45, 63, 199); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#0479FF" data-value="#0479FF"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(4, 121, 255); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#00B2FF" data-value="#00B2FF"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(0, 178, 255); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#00DAE1" data-value="#00DAE1"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(0, 218, 225); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#00A478" data-value="#00A478"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(0, 164, 120); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#4ABD32" data-value="#4ABD32"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(74, 189, 50); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#FF9D00" data-value="#FF9D00"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(255, 157, 0); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#FF6200" data-value="#FF6200"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(255, 98, 0); border-radius: 4px;"></div></li><li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button" tabindex="-1" role="option" aria-disabled="false" style="padding-left: 8px; padding-right: 8px;" title="#5E7A8C" data-value="#5E7A8C"><div style="position: relative; height: 24px; width: 24px; background-color: rgb(94, 122, 140); border-radius: 4px;"></div></li></ul></div>');
|
|
|
|
$Selector.css('z-index', '10000').find('li').click(setColor);
|
|
//Background
|
|
$Background = $('<div>', {'aria-hidden':'true', 'style':'position: fixed; inset: 0px; background-color: transparent;'}).click(function(){toggleSelector(false);});
|
|
|
|
//Add Selector & background to DOM
|
|
$Selector.add($Background).hide().appendTo('body');
|
|
|
|
//Extra style
|
|
$('body').append($('<style>').text('@keyframes rainbow { 0%, 100% {background-color: red;} 17% {background-color: orange;} 33% {background-color: yellow;} 50% {background-color: green;} 67% {background-color: blue;} 83% {background-color: purple;} }'));
|
|
|
|
//Button for mass update
|
|
$MassUpdate = $('<button>', {'type':'button', 'class':'ga-button ga-button-flat ga-toolbar-button', 'disabled':'disabled'})
|
|
.data('track-id', 'mass')
|
|
.click(function(){toggleSelector(true, $(this));})
|
|
.append($('<i>', {'class':'material-icons ibmid'}).text('color_lens'))
|
|
.append(' ')
|
|
.append($('<span>', {'class':'ibmid ga-toolbar-button-text'}).text('Change Color'));
|
|
|
|
$('#DatasummaryController .ga-toolbar .ga-toolbar-left .ga-button').eq(1).after($MassUpdate);
|
|
|
|
//Event on checkboxes to enable mass icon button
|
|
$('.ngGrid .col0 input[type="checkbox"]').change(function(){
|
|
$MassUpdate.prop('disabled', ($('.ngGrid .col0 input[type="checkbox"]:checked').length == 0));
|
|
});
|
|
|
|
//DOM Elements
|
|
$Grid = $('.ngGrid');
|
|
$Head = $Grid.find('.ngTopPanel');
|
|
$Body = $Grid.find('.ngViewport');
|
|
|
|
iColorColLeft = $Grid.find('.colt0').width();
|
|
iCol1Width = $Grid.find('.ngHeaderCell.ng-scope.col1.colt1').width();
|
|
iCol1Left = parseInt($Grid.find('.ngHeaderCell.ng-scope.col1.colt1').css('left'));
|
|
|
|
//Insert column header
|
|
$Head.find('.ngHeaderContainer .ngHeaderCell.col0').after(
|
|
$('<div>', {'class':'ngHeaderCell ng-scope col0-1 colt0-1', 'style':'width:'+iColorColWidth+'px; left:'+iColorColLeft+'px;'})
|
|
.append($('<div>', {'class':'ngVerticalBar ngVerticalBarVisible', 'style':'height: '+iColorColHeight+'px;'}).text(' '))
|
|
.append($('<div>')
|
|
.append($('<div>', {'class':'ngHeaderSortColumn ngSorted', 'style':'cursor: pointer;'})
|
|
.append($('<div>', {'class':'ngHeaderText ng-binding', 'style':'width:'+iColorColWidth+'px;'}).text('Color'))
|
|
)
|
|
)
|
|
);
|
|
$Head.find('.ngHeaderCell.colt1').width(iCol1Width - iColorColWidth);
|
|
$Head.find('.col1').width(iCol1Width - iColorColWidth).css('left', (iCol1Left + iColorColWidth)+'px');
|
|
|
|
//Update Colors
|
|
update();
|
|
|
|
//Event on DOM change: First track of the page
|
|
oObserver = new MutationObserver((oMutations) => {update();});
|
|
oObserver.observe($('.ngGrid .ngCanvas .ngCell.col1 .ngCellText.col1 .ng-binding')[0], {attributes: true});
|
|
}
|
|
|
|
function wait(fIsFinished, fAction) {
|
|
console.log('waiting for page to load');
|
|
if(typeof oWaitTimer != "undefined") clearTimeout(oWaitTimer);
|
|
if(fIsFinished()) fAction();
|
|
else { oWaitTimer = setTimeout(function(){wait(fIsFinished, fAction);}, 100); }
|
|
}
|
|
|
|
function update(bWaited) {
|
|
bWaited = bWaited || false;
|
|
|
|
if(!bWaited) {
|
|
if(typeof oTimer != "undefined") clearTimeout(oTimer);
|
|
oTimer = setTimeout((() => {update(true);}), 200);
|
|
return;
|
|
}
|
|
|
|
oObserver.disconnect();
|
|
oObserver.observe($('.ngGrid .ngCanvas .ngCell.col1 .ngCellText.col1 .ng-binding')[0], {attributes: true});
|
|
|
|
console.log('updating');
|
|
|
|
$Body.find('.ngRow').each(function(key, elem){
|
|
var $Row = $(elem);
|
|
var sTrackId = $Row.find('.col1 a.ng-binding').attr('href').split('/')[3];
|
|
|
|
setTrackInfo(sTrackId, function(oData){refreshRow(oData.row, oData.track.id);}, {row:$Row});
|
|
});
|
|
}
|
|
|
|
function setTrackInfo(sTrackId, fOnDone, oVars) {
|
|
oVars = oVars || {};
|
|
if(!asTracks[sTrackId].post) {
|
|
$.get({url:'https://www.gaiagps.com/api/objects/track/'+sTrackId+'/', id:sTrackId})
|
|
.done(function(asTrack) {
|
|
asTracks[this.id].post = asTrack;
|
|
oVars.track = asTracks[this.id];
|
|
fOnDone(oVars);
|
|
})
|
|
.fail(function(){
|
|
setTrackInfo(sTrackId, fOnDone, oVars);
|
|
});
|
|
}
|
|
else {
|
|
oVars.track = asTracks[sTrackId];
|
|
fOnDone(oVars);
|
|
}
|
|
}
|
|
|
|
function refreshRow($Row, sTrackId) {
|
|
//Color
|
|
var sColor = asTracks[sTrackId].post.features[0].properties.hexcolor;
|
|
if(!sColor) sColor = 'rgb(0,0,0)';
|
|
|
|
//Add Color
|
|
if(!$Row.find('.ngCell.col0-1.colt0-1').length) {
|
|
//Move Col1
|
|
$Row.find('.colt1').width(iCol1Width - iColorColWidth);
|
|
$Row.find('.col1').width(iCol1Width - iColorColWidth).css('left', (iCol1Left + iColorColWidth)+'px');
|
|
|
|
$Row.find('.ngCell.col0.colt0').after(
|
|
$('<div>', {'class':'ngCell col0-1 colt0-1', 'style':'cursor: pointer; width:'+iColorColWidth+'px; left:'+iColorColLeft+'px;'})
|
|
.data('color', sColor)
|
|
.data('track-id', sTrackId)
|
|
.append($('<div>', {'class':'ngVerticalBar ngVerticalBarVisible', 'style':'height: '+iColorColHeight+'px;'}))
|
|
.append($('<div>')
|
|
.append($('<div>', {'style':'ngSelectionCell'})
|
|
.append($('<div>', {'class':'track-color', 'style':'position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); height: 24px; width: 24px; background-color: '+sColor+'; border-radius: 4px;'}))
|
|
)
|
|
)
|
|
//Display Selector
|
|
.click(function(){
|
|
toggleSelector(null, $(this));
|
|
})
|
|
);
|
|
}
|
|
//Update Color
|
|
else {
|
|
$Row.find('.ngCell.col0-1.colt0-1')
|
|
.data('color', sColor)
|
|
.data('track-id', sTrackId)
|
|
.find('.track-color')
|
|
.css('background', sColor);
|
|
}
|
|
}
|
|
|
|
function toggleSelector(bShow, $Track){
|
|
bShow = (bShow == null)?(!$Selector.is(':visible')):bShow;
|
|
$Selector.add($Background).toggle(bShow);
|
|
if(bShow) {
|
|
$Selector
|
|
.data('track', $Track)
|
|
.css({top: ($Track.offset().top + iColorColHeight)+'px', left: ($Track.offset().left)+'px'})
|
|
.find('li[data-value="'+$Track.data('color')+'"]').addClass('Mui-selected');
|
|
}
|
|
else {
|
|
$Selector
|
|
.find('li.Mui-selected').removeClass('Mui-selected');
|
|
}
|
|
return bShow;
|
|
}
|
|
|
|
function getTrackDOm(sTrackId) {
|
|
var $Link = $('a[href="/datasummary/track/'+sTrackId+'/"]');
|
|
return ($Link.length == 0)?null:$Link.parents('.ngRow').find('.ngCell.col0-1');
|
|
}
|
|
|
|
function setColor(){
|
|
var sColor = $(this).attr('data-value');
|
|
|
|
//List of tracks to change (selected checkboxes or just the one)
|
|
a$Tracks = [];
|
|
if($Selector.data('track').data('track-id') == 'mass') {
|
|
if($('[ng-show="selectAllFromAllPages"]').is(':visible')) {
|
|
for(i in asTracks) {
|
|
var $Row = getTrackDOm(asTracks[i].id);
|
|
if(!$Row) {
|
|
$Row = $('<div>')
|
|
.data('track-id', asTracks[i].id)
|
|
.append($('<div>', {'class':'track-color'}));
|
|
}
|
|
|
|
a$Tracks.push($Row);
|
|
}
|
|
}
|
|
else { a$Tracks = $('.ngGrid .ngViewport .ngRow .ngCell.col0 .ngSelectionCheckbox:checked').parents('.ngRow').find('.ngCell.col0-1').toArray(); }
|
|
}
|
|
else { a$Tracks.push($Selector.data('track')); }
|
|
|
|
console.log('nb of tracks to modify: '+a$Tracks.length);
|
|
|
|
setTrackColor(sColor, 0);
|
|
}
|
|
|
|
function setTrackColor(sColor, iIndex) {
|
|
var $Track = $(a$Tracks[iIndex]);
|
|
|
|
//Ajax Loader
|
|
$Track.find('.track-color').css('animation', 'rainbow 1s infinite');
|
|
|
|
var sTrackId = $Track.data('track-id');
|
|
|
|
setTrackInfo(
|
|
sTrackId,
|
|
function(oData){
|
|
asTracks[oData.track.id].post.features[0].properties.color = oData.color;
|
|
asTracks[oData.track.id].post.features[0].properties.hexcolor = oData.color;
|
|
|
|
var asPost = {
|
|
type: asTracks[oData.track.id].post.features[0].type,
|
|
properties: asTracks[oData.track.id].post.features[0].properties,
|
|
geometry: asTracks[oData.track.id].post.features[0].geometry,
|
|
};
|
|
asPost.properties.localId = oData.track.id;
|
|
|
|
$.ajax({
|
|
url: 'https://www.gaiagps.com/api/objects/track/'+oData.track.id+'/',
|
|
type: 'PUT',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(asPost),
|
|
id: oData.track.id
|
|
})
|
|
.done(function(){
|
|
setTrackInfo(
|
|
this.id,
|
|
function(oData) {
|
|
iIndex++;
|
|
$('[ng-show="selectAllFromAllPages"]:visible').text(iIndex+'/'+a$Tracks.length);
|
|
var $Track = getTrackDOm(oData.track.id);
|
|
if($Track) {
|
|
$Track.find('.track-color').css({'background': oData.color, 'animation':'none'});
|
|
toggleSelector(false, $Track);
|
|
}
|
|
if(iIndex < a$Tracks.length) setTrackColor(oData.color, iIndex);
|
|
},
|
|
{color:oData.color, force_update:true}
|
|
);
|
|
})
|
|
.fail(()=>{
|
|
var $Track = getTrackDOm(oData.track.id);
|
|
if($Track) $Track.find('.track-color').css({'animation':'none'});
|
|
setTrackColor(oData.color, iIndex);
|
|
});
|
|
},
|
|
{color:sColor}
|
|
);
|
|
}
|
|
|
|
var iColorColWidth = 50, iColorColHeight = 59;
|
|
|
|
//Tracks
|
|
asTracks = {};
|
|
$.ajax({url:'https://www.gaiagps.com/api/objects/track/?routepoints=false&show_archived=false&show_filed=true'}).done((asData) => {
|
|
for(var i in asData) { asTracks[asData[i].id] = asData[i]; }
|
|
wait(function(){return ($('.ngViewport .ngRow').length > 0);}, init);
|
|
});
|