1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/a3e2c3464298/ Changeset: a3e2c3464298 User: guerler Date: 2013-12-18 23:16:43 Summary: Grids: Push code into js, async refresh based on json Affected #: 3 files diff -r 350c72df26815c0483a268fd1a097f0af8360930 -r a3e2c3464298ebea3fd2ab93a43aac479ba9665a static/scripts/galaxy.grids.js --- a/static/scripts/galaxy.grids.js +++ b/static/scripts/galaxy.grids.js @@ -130,7 +130,13 @@ }); return url_data; + }, + + // Return URL for obtaining a new grid + get_url: function (args) { + return this.get('url_base') + "?" + $.param(this.get_url_data()) + '&' + $.param(args); } + }); // grid view @@ -140,9 +146,10 @@ grid: null, // Initialize - initialize: function(grid) + initialize: function(grid_config) { - this.init_grid(grid); + // initialize controls + this.init_grid(grid_config); this.init_grid_controls(); // Initialize text filters to select text on click and use normal font when user is typing. @@ -153,9 +160,30 @@ }, // Initialize - init_grid: function(grid) + init_grid: function(grid_config) { - this.grid = grid; + // link grid model + this.grid = new Grid(grid_config); + + // get options + var options = this.grid.attributes; + + // strip protocol and domain + var url = this.grid.get('url_base'); + url = url.replace(/^.*\/\/[^\/]+/, ''); + this.grid.set('url_base', url); + + // update div contents + $('#grid-table-body').html(this.template_body(options)); + $('#grid-table-footer').html(this.template_footer(options)); + + // update message + if (options.message) { + $('#grid-message').html(this.template_message(options)); + setTimeout( function() { $('#grid-message').html(''); }, 5000); + } + + // configure elements this.init_grid_elements(); }, @@ -537,7 +565,7 @@ // check for operation details if (operation && id) { // show confirmation box - if (confirmation_text && confirmation_text != '' && confirmation_text != 'None') + if (confirmation_text && confirmation_text != '' && confirmation_text != 'None' && confirmation_text != 'null') if(!confirm(confirmation_text)) return false; @@ -622,30 +650,16 @@ type: method, url: self.grid.get('url_base'), data: self.grid.get_url_data(), - error: function(response) { alert( "Grid refresh failed" );}, + error: function(response) { alert( 'Grid refresh failed' );}, success: function(response_text) { - // HACK: use a simple string to separate the elements in the - // response: (1) table body; (2) number of pages in table; and (3) message. - var parsed_response_text = response_text.split("*****"); - - // Update grid body and footer. - $('#grid-table-body').html(parsed_response_text[0]); - // FIXME: this does not work at all; what's needed is a function - // that updates page links when number of pages changes. - $('#grid-table-footer').html(parsed_response_text[1]); - + // Initialize new grid config + self.init_grid($.parseJSON(response_text)); + // Trigger custom event to indicate grid body has changed. $('#grid-table-body').trigger('update'); // Hide loading overlay. $('.loading-elt-overlay').hide(); - - // Show message if there is one. - var message = $.trim( parsed_response_text[2] ); - if (message !== "") { - $('#grid-message').html( message ).show(); - setTimeout( function() { $('#grid-message').hide(); }, 5000); - } }, complete: function() { // Clear grid of transient request attributes. @@ -688,6 +702,253 @@ if (cur_page !== null && cur_page !== undefined && cur_page !== 'all') { this.grid.set('cur_page', 1); } + }, + + // template + template_body: function(options) { + // initialize + var tmpl = ''; + var num_rows_rendered = 0; + var items_length = options.items.length; + + // empty grid? + if (items_length == 0) { + // No results. + tmpl += '<tr><td colspan="100"><em>No Items</em></td></tr>'; + num_rows_rendered = 1; + } + + // create rows + for (i in options.items) { + + // encode ids + var item = options.items[i]; + var encoded_id = item.encode_id; + var popupmenu_id = 'grid-' + i + '-popup'; + + // Tag current + tmpl += '<tr '; + if (options.current_item_id == item.id) { + tmpl += 'class="current"'; + } + tmpl += '>'; + + // Item selection column + if (options.show_item_checkboxes) { + tmpl += '<td style="width: 1.5em;">' + + '<input type="checkbox" name="id" value="' + encoded_id + '" id="' + encoded_id + '" class="grid-row-select-checkbox" />' + + '</td>'; + } + + // Data columns + for (j in options.columns) { + var column = options.columns[j]; + if (column.visible) { + // Nowrap + var nowrap = ''; + if (column.nowrap) { + nowrap = 'style="white-space:nowrap;"'; + } + + // get column settings + var column_settings = item.column_config[column.label]; + + // load attributes + var link = column_settings.link; + var value = column_settings.value; + var inbound = column_settings.inbound; + + // unescape value + if (jQuery.type( value ) === 'string') { + value = value.replace(/\/\//g, '/'); + } + + // Attach popup menu? + var id = ""; + var cls = ""; + if (column.attach_popup) { + id = 'grid-' + i + '-popup'; + cls = "menubutton" + if (link != '') { + cls += " split"; + } + cls += " popup"; + } + + // Check for row wrapping + tmpl += '<td ' + nowrap + '>'; + + // Link + if (link) { + if (options.operations.length != 0) { + tmpl += '<div id="' + id + '" class="' + cls + '" style="float: left;">'; + } + + var label_class = ""; + if (inbound) { + label_class = "use-inbound" + } else { + label_class = "use-outbound" + } + tmpl += '<a class="label ' + label_class + '" href="' + link + '" onclick="return false;">' + value + '</a>'; + if (options.operations.length != 0) { + tmpl += '</div>'; + } + } else { + tmpl += '<div id="' + id + '" class="' + cls + '"><label id="' + column.label_id_prefix + encoded_id + '" for="' + encoded_id + '">' + value + '</label></div>'; + } + tmpl += '</td>'; + } + } + tmpl += '</tr>'; + num_rows_rendered++; + } + return tmpl; + }, + + // template + template_footer: function(options) { + + // create template string + var tmpl = ''; + + // paging + if (options.use_paging && options.num_pages > 1) { + // get configuration + var num_page_links = options.num_page_links; + var cur_page_num = options.cur_page_num; + var num_pages = options.num_pages; + + // First pass on min page. + var page_link_range = num_page_links / 2; + var min_page = cur_page_num - page_link_range + var min_offset = 0; + if (min_page == 0) { + // Min page is too low. + min_page = 1; + min_offset = page_link_range - ( cur_page_num - min_page ); + } + + // Set max page. + var max_range = page_link_range + min_offset; + var max_page = cur_page_num + max_range; + if (max_page <= num_pages) { + // Max page is fine. + max_offset = 0; + } else { + // Max page is too high. + max_page = num_pages; + // +1 to account for the +1 in the loop below. + max_offset = max_range - ( max_page + 1 - cur_page_num ); + } + + // Second and final pass on min page to add any unused + // offset from max to min. + if (max_offset != 0) { + min_page -= max_offset + if (min_page < 1) { + min_page = 1 + } + } + + // template header + tmpl += '<tr id="page-links-row">'; + if (options.show_item_checkboxes) { + tmpl += '<td></td>'; + } + tmpl += '<td colspan="100">' + + '<span id="page-link-container">' + + 'Page:'; + + if (min_page > 1) { + tmpl += '<span class="page-link" id="page-link-1"><a href="' + this.grid.get_url({page : page_index}) + '" page_num="1" onclick="return false;">1</a></span> ...'; + } + + // create page urls + for (var page_index = min_page; page_index < max_page + 1; page_index++) { + + if (page_index == options.cur_page_num) { + tmpl += '<span class="page-link inactive-link" id="page-link-' + page_index + '">' + page_index + '</span>'; + } else { + tmpl += '<span class="page-link" id="page-link-' + page_index + '"><a href="' + this.grid.get_url({page : page_index}) + '" onclick="return false;" page_num="' + page_index + '">' + page_index + '</a></span>'; + } + } + + // show last page + if (max_page < num_pages) { + tmpl += '...' + + '<span class="page-link" id="page-link-' + num_pages + '"><a href="' + this.grid.get_url({page : num_pages}) + '" onclick="return false;" page_num="' + num_pages + '">' + num_pages + '</a></span>'; + } + tmpl += '</span>'; + + // Show all link + tmpl += '<span class="page-link" id="show-all-link-span"> | <a href="' + this.grid.get_url({page : 'all'}) + '" onclick="return false;" page_num="all">Show All</a></span>' + + '</td>' + + '</tr>'; + } + + // Grid operations for multiple items. + if (options.show_item_checkboxes) { + // start template + tmpl += '<tr>' + + '<input type="hidden" id="operation" name="operation" value="">' + + '<td></td>' + + '<td colspan="100">' + + 'For <span class="grid-selected-count"></span> selected ' + options.get_class_plural + ': '; + + // configure buttons for operations + for (i in options.operations) { + var operation = options.operations[i]; + if (operation.allow_multiple) { + tmpl += '<input type="button" value="' + operation.label + '" class="action-button" onclick="gridView.submit_operation(this, \'' + operation.confirm + '\')"> '; + } + } + + // finalize template + tmpl += '</td>' + + '</tr>'; + } + + // count global operations + var found_global = false; + for (i in options.operations) { + if (options.operations[i].global_operation) { + found_global = true; + break; + } + } + + // add global operations + if (found_global) { + tmpl += '<tr>' + + '<td colspan="100">'; + for (i in options.operations) { + var operation = options.operations[i]; + if (operation.global_operation) { + tmpl += '<a class="action-button" href="' + operation.global_operation + '">' + operation.label + '</a>'; + } + } + tmpl += '</td>' + + '</tr>'; + } + + // add legend + if (options.legend) { + tmpl += '<tr>' + + '<td colspan="100">' + options.legend + '</td>' + + '</tr>'; + } + + // return + return tmpl; + }, + + // template + template_message: function(options) { + return '<p>' + + '<div class="' + options.status + 'message transient-message">' + options.message + '</div>' + + '<div style="clear: both"></div>' + + '</p>'; } }); diff -r 350c72df26815c0483a268fd1a097f0af8360930 -r a3e2c3464298ebea3fd2ab93a43aac479ba9665a templates/grid_base.mako --- a/templates/grid_base.mako +++ b/templates/grid_base.mako @@ -1,6 +1,7 @@ <%! from galaxy.web.framework.helpers.grids import TextColumn, StateColumn, GridColumnFilter from galaxy.web.framework.helpers import iff + import urllib import galaxy.util def inherit(context): @@ -24,7 +25,7 @@ self.grid_javascripts() if embedded: self.render_grid_header( grid, False ) - self.render_grid_table( grid, show_item_checkboxes=show_item_checkboxes ) + self.render_grid_table( grid ) else: self.make_grid( grid ) endif @@ -50,6 +51,7 @@ 'show_item_checkboxes' : context.get('show_item_checkboxes', False), 'cur_page_num' : cur_page_num, 'num_pages' : num_pages, + 'num_page_links' : num_page_links, 'history_tag_autocomplete_url' : url( controller='tag', action='tag_autocomplete_data', item_class='History' ), 'history_name_autocomplete_url' : url( controller='history', action='name_autocomplete_data' ), 'status' : status, @@ -58,7 +60,6 @@ 'operations' : [], 'items' : [], 'columns' : [], - 'multiple_item_ops_exist' : None, 'get_class_plural' : get_class_plural( grid.model_class ).lower(), 'use_paging' : grid.use_paging, 'legend' : grid.legend, @@ -68,7 +69,7 @@ 'default_filter_dict' : default_filter_dict, 'advanced_search' : advanced_search } - + ## add current item if exists if current_item: self.grid_config['current_item_id'] = current_item.id @@ -119,7 +120,7 @@ 'global_operation' : False }) if operation.allow_multiple: - self.grid_config['multiple_item_ops_exist'] = True + self.grid_config['show_item_checkboxes'] = True if operation.global_operation: self.grid_config['global_operation'] = url( ** (operation.global_operation()) ) @@ -176,8 +177,6 @@ # Handle non-ascii chars. if isinstance(value, str): value = unicode(value, 'utf-8') - - # escape string value = value.replace('/', '//') endif @@ -242,7 +241,16 @@ } gridView.add_filter_condition("tags", tag); }; + + ## load grid viewer + $(function() { + require(['galaxy.grids'], function(mod_grids) { + gridView = new mod_grids.GridView(${h.to_json_string(self.grid_config)}); + }); + }); </script> + + ${handle_refresh_frames()} </%def><%def name="stylesheets()"> @@ -268,20 +276,13 @@ <td></td></tr><tr> - <td width="100%" id="grid-message" valign="top"> - %if message: - <p> - <div class="${self.grid_config['status']}message transient-message">${self.grid_config['message']}</div> - <div style="clear: both"></div> - </p> - %endif - </td> + <td width="100%" id="grid-message" valign="top"></td><td></td><td></td></tr></table> - ${self.render_grid_table( grid, show_item_checkboxes )} + ${self.render_grid_table( grid )} </%def><%def name="grid_title()"> @@ -328,16 +329,11 @@ </%def> ## Render grid. -<%def name="render_grid_table( grid, show_item_checkboxes=False)"> +<%def name="render_grid_table( grid )"><% # get configuration show_item_checkboxes = self.grid_config['show_item_checkboxes'] - multiple_item_ops_exist = self.grid_config['multiple_item_ops_exist'] sort_key = self.grid_config['sort_key'] - - # Show checkboxes if flag is set or if multiple item ops exist. - if show_item_checkboxes or multiple_item_ops_exist: - show_item_checkboxes = True %><form method="post" onsubmit="return false;"><table id="grid-table" class="grid"> @@ -364,238 +360,14 @@ </th> %endif %endfor - <th></th></tr></thead> - <tbody id="grid-table-body"> - ${render_grid_table_body_contents( grid, show_item_checkboxes )} - </tbody> - <tfoot id="grid-table-footer"> - ${render_grid_table_footer_contents( grid, show_item_checkboxes )} - </tfoot> + <tbody id="grid-table-body"></tbody> + <tfoot id="grid-table-footer"></tfoot></table></form></%def> -## Render grid table body contents. -<%def name="render_grid_table_body_contents(grid, show_item_checkboxes=False)"> - <% num_rows_rendered = 0 %> - %if len(self.grid_config['items']) == 0: - ## No results. - <tr><td colspan="100"><em>No Items</em></td></tr> - <% num_rows_rendered = 1 %> - %endif - %for i, item in enumerate( self.grid_config['items'] ): - <% encoded_id = item['encode_id'] %> - <% popupmenu_id = "grid-" + str(i) + "-popup" %> - <tr \ - %if self.grid_config['current_item_id'] == item['id']: - class="current" \ - %endif - > - ## Item selection column - %if show_item_checkboxes: - <td style="width: 1.5em;"> - <input type="checkbox" name="id" value="${encoded_id}" id="${encoded_id}" class="grid-row-select-checkbox" /> - </td> - %endif - ## Data columns - %for column in self.grid_config['columns']: - %if column['visible']: - <% - ## Nowrap - nowrap = "" - if column['nowrap']: - nowrap = 'style="white-space:nowrap;"' - - # get column settings - column_settings = item['column_config'][column['label']] - - # load attributes - link = column_settings['link'] - value = column_settings['value'] - inbound = column_settings['inbound'] - - # unescape value - if isinstance(value, unicode): - value = value.replace('//', '/') - - # Attach popup menu? - id = "" - cls = "" - if column['attach_popup']: - id = 'grid-%d-popup' % i - cls = "menubutton" - if link: - cls += " split" - endif - cls += " popup" - endif - %> - <td ${nowrap}> - %if link: - %if len(self.grid_config['operations']) != 0: - <div id="${id}" class="${cls}" style="float: left;"> - %endif - - <% - label_class = "" - if inbound: - label_class = "use-inbound" - else: - label_class = "use-outbound" - endif - %> - <a class="label ${label_class}" href="${link}" onclick="return false;">${value}</a> - %if len(self.grid_config['operations']) != 0: - </div> - %endif - %else: - <div id="${id}" class="${cls}"><label id="${column['label_id_prefix']}${encoded_id}" for="${encoded_id}">${value}</label></div> - %endif - </td> - %endif - %endfor - </tr> - <% num_rows_rendered += 1 %> - %endfor - - ## update configuration - <script type="text/javascript"> - $(function() { - require(['galaxy.grids'], function(mod_grids) { - ## get configuration - var grid_config = ${ h.to_json_string( self.grid_config ) }; - - // Create grid. - var grid = new mod_grids.Grid(grid_config); - - // strip protocol and domain - var url = grid.get('url_base'); - url = url.replace(/^.*\/\/[^\/]+/, ''); - grid.set('url_base', url); - - // Create view. - if (!gridView) - gridView = new mod_grids.GridView(grid); - else - gridView.init_grid(grid); - }); - }); - </script> - - ${handle_refresh_frames()} -</%def> - -## Render grid table footer contents. -<%def name="render_grid_table_footer_contents(grid, show_item_checkboxes=False)"> - <% - items_plural = self.grid_config['get_class_plural'] - num_pages = self.grid_config['num_pages'] - cur_page_num = self.grid_config['cur_page_num'] - %> - %if self.grid_config['use_paging'] and num_pages > 1: - <tr id="page-links-row"> - %if show_item_checkboxes: - <td></td> - %endif - <td colspan="100"> - <span id='page-link-container'> - ## Page links. Show 10 pages around current page. - <% - # - # Set minimum & maximum page. - # - page_link_range = num_page_links/2 - - # First pass on min page. - min_page = cur_page_num - page_link_range - if min_page >= 1: - # Min page is fine. - min_offset = 0 - else: - # Min page is too low. - min_page = 1 - min_offset = page_link_range - ( cur_page_num - min_page ) - - # Set max page. - max_range = page_link_range + min_offset - max_page = cur_page_num + max_range - if max_page <= num_pages: - # Max page is fine. - max_offset = 0 - else: - # Max page is too high. - max_page = num_pages - # +1 to account for the +1 in the loop below. - max_offset = max_range - ( max_page + 1 - cur_page_num ) - - # Second and final pass on min page to add any unused - # offset from max to min. - if max_offset != 0: - min_page -= max_offset - if min_page < 1: - min_page = 1 - %> - Page: - % if min_page > 1: - <span class='page-link' id="page-link-1"><a href="${url( page=1 )}" page_num="1" onclick="return false;">1</a></span> ... - % endif - %for page_index in range(min_page, max_page + 1): - %if page_index == cur_page_num: - <span class='page-link inactive-link' id="page-link-${page_index}">${page_index}</span> - %else: - <% args = { 'page' : page_index } %> - <span class='page-link' id="page-link-${page_index}"><a href="${url( args )}" onclick="return false;" page_num='${page_index}'>${page_index}</a></span> - %endif - %endfor - %if max_page < num_pages: - ... - <span class='page-link' id="page-link-${num_pages}"><a href="${url( page=num_pages )}" onclick="return false;" page_num="${num_pages}">${num_pages}</a></span> - %endif - </span> - - ## Show all link - <span class='page-link' id='show-all-link-span'> | <a href="${url( page='all' )}" onclick="return false;" page_num="all">Show All</a></span> - </td> - </tr> - %endif - ## Grid operations for multiple items. - %if show_item_checkboxes: - <tr> - ## place holder for multiple operation commands - <input type="hidden" id="operation" name="operation" value=""> - <td></td> - <td colspan="100"> - For <span class="grid-selected-count"></span> selected ${items_plural}: - %for operation in self.grid_config['operations']: - %if operation['allow_multiple']: - <input type="button" value="${operation['label']}" class="action-button" onclick="gridView.submit_operation(this, '${operation['confirm']}')"> - %endif - %endfor - </td> - </tr> - %endif - %if len([o for o in self.grid_config['operations'] if o['global_operation']]) > 0: - <tr> - <td colspan="100"> - %for operation in self.grid_config['operations']: - %if operation['global_operation']: - <a class="action-button" href="${operation['global_operation']}">${operation['label']}</a> - %endif - %endfor - </td> - </tr> - %endif - %if self.grid_config['legend']: - <tr> - <td colspan="100"> - ${self.grid_config['legend']} - </td> - </tr> - %endif -</%def> - ## Print grid search/filtering UI. <%def name="render_grid_filters( grid, render_advanced_search=True )"><% diff -r 350c72df26815c0483a268fd1a097f0af8360930 -r a3e2c3464298ebea3fd2ab93a43aac479ba9665a templates/grid_base_async.mako --- a/templates/grid_base_async.mako +++ b/templates/grid_base_async.mako @@ -1,18 +1,4 @@ -<%namespace file="./grid_base.mako" import="*" /> -<%namespace file="/display_common.mako" import="render_message" /> +<%namespace name="grid_base" file="./grid_base.mako" import="*" /> ${init()} - -<% - # Set flag to indicate whether grid has operations that operate on multiple items. - multiple_item_ops_exist = False - for operation in grid.operations: - if operation.allow_multiple: - multiple_item_ops_exist = True -%> - -${render_grid_table_body_contents( grid, show_item_checkboxes=( show_item_checkboxes or multiple_item_ops_exist ) )} -***** -${render_grid_table_footer_contents( grid, show_item_checkboxes=( show_item_checkboxes or multiple_item_ops_exist ) )} -***** -${render_message( message, status )} \ No newline at end of file +${h.to_json_string( grid_base.grid_config )} \ No newline at end of file Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.