X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/6a2406f04875497a7bfad72fc8bcd73b792fefae..47221ee04bee623850c559274b5ff64fe3068ae6:/apps/workbench/app/assets/javascripts/tab_panes.js diff --git a/apps/workbench/app/assets/javascripts/tab_panes.js b/apps/workbench/app/assets/javascripts/tab_panes.js index 9586e4c10b..7e2527eda6 100644 --- a/apps/workbench/app/assets/javascripts/tab_panes.js +++ b/apps/workbench/app/assets/javascripts/tab_panes.js @@ -1,29 +1,147 @@ -$(document).on('shown.bs.tab', '[data-toggle="tab"]', function(e) { - var content_url = $(e.target).attr('data-pane-content-url'); - var $pane = $($(e.target).attr('href')); - if ($pane.hasClass('loaded')) - return; - $.ajax(content_url, {dataType: 'html', type: 'GET', context: $pane}). - done(function(data, status, jqxhr) { - $('> div > div', this).html(data); - $(this).addClass('loaded'); - }); +// Load tab panes on demand. See app/views/application/_content.html.erb + +// Fire when a tab is selected/clicked. +$(document).on('shown.bs.tab', '[data-toggle="tab"]', function(event) { + var tgt = $($(event.relatedTarget).attr('href')); + $(".pane-anchor", tgt).each(function (i, e) { + var a = $($(e).attr('href')); + a.removeClass("active"); + }); + + tgt = $($(event.target).attr('href')); + $(".pane-anchor", tgt).each(function (i, e) { + var a = $($(e).attr('href')); + a.addClass("active"); + }); + + $(event.target).trigger('arv:pane:reload'); }); -$(document).on('arv:pane:reload', '.tab-pane', function() { - // Unload a single pane. Reload it if it's active. - $(this).removeClass('loaded'); - if ($(this).hasClass('active')) { - $('[href=#' + $(this).attr('id') + ']').trigger('shown.bs.tab'); +// Ask a refreshable pane to reload via ajax. +// Target of this event is the anchoring element that manages the pane. +// Panes can be in one of four states: not loaded (no state classes), pane-loading, pane-loading+pane-stale, pane-loaded +$(document).on('arv:pane:reload', function(e) { + e.stopPropagation(); + + if ($(e.target).hasClass('pane-loading')) { + // Already loading, mark stale to schedule a reload after this one. + console.log(e.target.id + " stale"); + $(e.target).addClass('pane-stale'); + return; + } + + var throttle = $(e.target).attr('data-load-throttle'); + if (throttle) { + var now = (new Date()).getTime(); + var loaded_at = $(e.target).attr('data-loaded-at'); + if (loaded_at && (now - loaded_at) < throttle) { + setTimeout(function() { + $(e.target).trigger('arv:pane:reload'); + }); + return; + } + } + + var $pane = $($(e.target).attr('href')); + if ($pane.hasClass('active')) { + console.log(e.target.id + " loading"); + + $(e.target).removeClass('pane-loaded'); + $(e.target).removeClass('pane-stale'); + $(e.target).addClass('pane-loading'); + + var content_url = $(e.target).attr('data-pane-content-url'); + $.ajax(content_url, {dataType: 'html', type: 'GET', context: $pane}). + done(function(data, status, jqxhr) { + // Preserve collapsed state + var collapsable = {}; + $(".collapse", $pane).each(function(i, c) { + collapsable[c.id] = $(c).hasClass('in'); + }); + var tmp = $(data); + $(".collapse", tmp).each(function(i, c) { + if (collapsable[c.id]) { + $(c).addClass('in'); + } else { + $(c).removeClass('in'); + } + }); + $pane.html(tmp); + $(e.target).removeClass('pane-loading'); + $(e.target).addClass('pane-loaded'); + $(e.target).attr('data-loaded-at', (new Date()).getTime()); + $pane.trigger('arv:pane:loaded'); + + console.log(e.target.id + " loaded"); + + if ($(e.target).hasClass('pane-stale')) { + $(e.target).trigger('arv:pane:reload'); + } + }).fail(function(jqxhr, status, error) { + var errhtml; + if (jqxhr.getResponseHeader('Content-Type').match(/\btext\/html\b/)) { + var $response = $(jqxhr.responseText); + var $wrapper = $('div#page-wrapper', $response); + if ($wrapper.length) { + errhtml = $wrapper.html(); + } else { + errhtml = jqxhr.responseText; + } + } else { + errhtml = ("An error occurred: " + + (jqxhr.responseText || status)). + replace(/&/g, '&'). + replace(//g, '>'); + } + $pane.html('
' + + '' + + ' ' + + 'Reload tab