From af8f410684a909403de4b431901298337c19088c Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 2 Jun 2015 15:39:08 +0200 Subject: [PATCH] Updated the CMS pagination component. Harmonized count type to NATURAL_64 for recent_nodes (more to do later). Fix get is active code. --- cms-safe.ecf | 1 + cms.ecf | 1 + examples/demo/site/scripts/node.sql | 2 +- modules/node/cms_node_api.e | 4 +- .../node/handler/cms_node_pagination_helper.e | 161 ---------- modules/node/handler/nodes_handler.e | 39 ++- modules/node/persistence/cms_node_storage_i.e | 7 +- .../node/persistence/cms_node_storage_null.e | 2 +- .../node/persistence/cms_node_storage_sql.e | 14 +- src/kernel/form/cms_lower_upper_pager.e | 15 + .../cms_data_query_parameters.e} | 45 ++- src/persistence/sql/cms_storage_sql_i.e | 15 + src/service/cms_api_options.e | 6 + src/service/response/cms_response.e | 3 + src/support/cms_pagination.e | 50 --- src/support/cms_pagination_generator.e | 287 ++++++++++++++++++ 16 files changed, 417 insertions(+), 235 deletions(-) delete mode 100644 modules/node/handler/cms_node_pagination_helper.e create mode 100644 src/kernel/form/cms_lower_upper_pager.e rename src/{support/cms_ordered_pagination.e => persistence/cms_data_query_parameters.e} (61%) delete mode 100644 src/support/cms_pagination.e create mode 100644 src/support/cms_pagination_generator.e diff --git a/cms-safe.ecf b/cms-safe.ecf index 91fdb85..d1c2b3c 100644 --- a/cms-safe.ecf +++ b/cms-safe.ecf @@ -24,6 +24,7 @@ + diff --git a/cms.ecf b/cms.ecf index f642c2a..4b9f7d6 100644 --- a/cms.ecf +++ b/cms.ecf @@ -24,6 +24,7 @@ + diff --git a/examples/demo/site/scripts/node.sql b/examples/demo/site/scripts/node.sql index 565b03f..0c99eef 100644 --- a/examples/demo/site/scripts/node.sql +++ b/examples/demo/site/scripts/node.sql @@ -6,7 +6,7 @@ CREATE TABLE "nodes" ( "type" TEXT NOT NULL, "title" VARCHAR(255) NOT NULL, "summary" TEXT, - "content" TEXT NOT NULL, + "content" TEXT, "format" VARCHAR(128), "author" INTEGER, "publish" DATETIME, diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 8de31a4..5e606a7 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -202,7 +202,7 @@ feature -- URL feature -- Access: Node - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 do Result := node_storage.nodes_count end @@ -220,7 +220,7 @@ feature -- Access: Node Result := node_storage.trashed_nodes (a_user.id) end - recent_nodes (a_pagination: CMS_PAGINATION): ITERABLE [CMS_NODE] + recent_nodes (a_pagination: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE] -- List of the `a_rows' most recent nodes starting from `a_offset'. do Result := node_storage.recent_nodes (a_pagination.offset.to_integer_32, a_pagination.size.to_integer_32) diff --git a/modules/node/handler/cms_node_pagination_helper.e b/modules/node/handler/cms_node_pagination_helper.e deleted file mode 100644 index c3b48ed..0000000 --- a/modules/node/handler/cms_node_pagination_helper.e +++ /dev/null @@ -1,161 +0,0 @@ -note - description: "Helper class to build the html pagination links and header summary" - date: "$Date$" - revision: "$Revision$" - -class - CMS_NODE_PAGINATION_HELPER - -create - make - -feature {NONE} -- Initialization - - make (a_resource: READABLE_STRING_8; req: WSF_REQUEST; a_response: CMS_RESPONSE; a_nodes_count: INTEGER_64) - -- Create an object with default values. - do - make_size (a_resource, req, a_response, a_nodes_count, 5) - end - - make_size (a_resource: READABLE_STRING_8; req: WSF_REQUEST; a_response: CMS_RESPONSE; a_nodes_count: INTEGER_64; a_page_size: NATURAL) - -- Create an object with a pages of size `a_page_size'. - do - create resource.make_from_string (a_resource) - number_of_nodes := a_nodes_count - create pager.make (0, a_page_size) - response := a_response - process (req) - end - - process (req: WSF_REQUEST) - -- Process request query paraments to build the pager. - do - --TODO: at the moment the code looks for hardcoded parameters - -- size and page, maybe we can parametrize these names. - -- Size:limit. - if - attached {WSF_STRING} req.query_parameter ("size") as l_size and then - attached l_size.value as l_value and then - l_value.is_natural - then - pager.set_size (l_value.to_natural_32) - end - - --Page:offset - if - attached {WSF_STRING} req.query_parameter ("page") as l_page and then - l_page.is_integer - then - current_page := l_page.integer_value - if current_page > 1 then - pager.set_offset ((current_page - 1).to_natural_32 * pager.size) - end - else - current_page := 1 - end - end - -feature -- Access - - pager: CMS_PAGINATION - -- Paginator. - - resource: IMMUTABLE_STRING_8 - - current_page: INTEGER - -- current page. - - number_of_pages: INTEGER_64 - -- total number of pages. - do - Result := (number_of_nodes // pager.size.as_integer_32) + 1 - end - - number_of_nodes: INTEGER_64 - -- number of nodes. - - response: CMS_RESPONSE - -- cms response - -feature -- Parameters - - page_parameter: STRING = "page" - - size_parameter: STRING = "size" - -feature -- Paginator - - append_pagination_summary_to (a_output: STRING) - -- Header summary - -- Current page 1 of n pages. - do - a_output.append ("

Items:

") - - a_output.append ("

Current Page:") - a_output.append_integer (current_page) - a_output.append (" of ") - a_output.append_integer_64 (number_of_pages) - a_output.append (" pages

") - end - - append_html_pager_to (a_output: STRING) - -- Append html pager to `a_output'. - -- note: First, [Prev], [Next], Last. - local - lnk: CMS_LOCAL_LINK - s: STRING - do - -- NOTE: for development purposes we have the following hardcode output. - -- pager - a_output.append ("
    %N") - create s.make_from_string (resource) - append_query_parameters_to (s, "1", pager.size.out) - create lnk.make ("First", s) - a_output.append ("
  • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
  • ") - if (current_page - 1) > 1 then - create s.make_from_string (resource) - append_query_parameters_to (s, (current_page - 1).out, pager.size.out) - - create lnk.make ("Prev", s) - a_output.append ("
  • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
  • ") - end - - if (current_page + 1) < number_of_pages then - create s.make_from_string (resource) - append_query_parameters_to (s, (current_page + 1).out, pager.size.out) - create lnk.make ("Next", s) - a_output.append ("
  • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
  • ") - end - create s.make_from_string (resource) - append_query_parameters_to (s, number_of_pages.out, pager.size.out) - create lnk.make ("Last", s) - a_output.append ("
  • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
  • ") - - a_output.append ("
%N") - end - - append_query_parameters_to (s: STRING; a_page: STRING; a_size: STRING) - do - if s.has ('?') then - s.append ("&") - else - s.append ("?") - end - s.append (page_parameter) - s.append_character ('=') - s.append (a_page) - s.append_character ('&') - s.append (size_parameter) - s.append_character ('=') - s.append (a_size) - end - -end diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 58839cb..974a17d 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -41,20 +41,36 @@ feature -- HTTP Methods s: STRING n: CMS_NODE lnk: CMS_LOCAL_LINK - l_page_helper: CMS_NODE_PAGINATION_HELPER + l_page_helper: CMS_PAGINATION_GENERATOR + s_pager: STRING + l_count: NATURAL_64 do - -- At the moment the template is hardcoded, but we can + -- At the moment the template are hardcoded, but we can -- get them from the configuration file and load them into -- the setup class. + l_count := node_api.nodes_count + create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) - create l_page_helper.make ("nodes/", req, l_response, node_api.nodes_count) create s.make_empty - l_page_helper.append_pagination_summary_to (s) - l_page_helper.append_html_pager_to (s) + if l_count > 1 then + l_response.set_title ("Listing " + l_count.out + " nodes") + else + l_response.set_title ("Listing " + l_count.out + " node") + end - if attached node_api.recent_nodes (l_page_helper.pager) as lst then + create s_pager.make_empty + create l_page_helper.make ("nodes/?page={page}&size={size}", node_api.nodes_count, 25) -- FIXME: Make this default page size a global CMS settings + l_page_helper.get_setting_from_request (req) + if l_page_helper.pages_count > 1 then + l_page_helper.append_to_html (l_response, s_pager) + if l_page_helper.page_size > 20 then + s.append (s_pager) + end + end + + if attached node_api.recent_nodes (l_page_helper.query_parameters) as lst then s.append ("
    %N") across lst as ic @@ -63,14 +79,21 @@ feature -- HTTP Methods lnk := node_api.node_link (n) s.append ("
  • ") s.append (l_response.link (lnk.title, lnk.location, Void)) + debug + if attached node_api.content_type (n.content_type) as ct then + s.append ("") + s.append (html_encoded (ct.title)) + s.append ("") + end + end s.append ("
  • %N") end s.append ("
%N") end - l_page_helper.append_html_pager_to (s) + -- Again the pager at the bottom, if needed + s.append (s_pager) l_response.set_main_content (s) - l_response.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
", Void), "highlighted") l_response.execute end diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index e24fe27..970c2bf 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -43,6 +43,8 @@ feature {NONE} -- Implementation extended_store (a_node: CMS_NODE) -- Store extended data from `a_node'. + require + not error_handler.has_error do if attached node_storage_extension (a_node) as ext then ext.store_node (a_node) @@ -51,16 +53,17 @@ feature {NONE} -- Implementation extended_load (a_node: CMS_NODE) -- Load extended data into `a_node'. + require + not error_handler.has_error do if attached node_storage_extension (a_node) as ext then ext.load_node (a_node) end end - feature -- Access - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 -- Count of nodes. deferred end diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e index b5a9406..0bb571e 100644 --- a/modules/node/persistence/cms_node_storage_null.e +++ b/modules/node/persistence/cms_node_storage_null.e @@ -30,7 +30,7 @@ feature -- Error Handling feature -- Access: node - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 -- Count of nodes. do end diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index b409851..188c56e 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -22,14 +22,14 @@ create feature -- Access - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 -- Number of items nodes. do error_handler.reset write_information_log (generator + ".nodes_count") sql_query (sql_select_nodes_count, Void) if sql_rows_count = 1 then - Result := sql_read_integer_64 (1) + Result := sql_read_natural_64 (1) end end @@ -267,8 +267,14 @@ feature {NONE} -- Implementation a_node.set_revision (1) -- New object. end end - extended_store (a_node) - sql_commit_transaction + if not error_handler.has_error then + extended_store (a_node) + end + if error_handler.has_error then + sql_rollback_transaction + else + sql_commit_transaction + end end feature -- Helpers diff --git a/src/kernel/form/cms_lower_upper_pager.e b/src/kernel/form/cms_lower_upper_pager.e new file mode 100644 index 0000000..f46e19b --- /dev/null +++ b/src/kernel/form/cms_lower_upper_pager.e @@ -0,0 +1,15 @@ +note + description: "Pager widget for ROC CMS." + date: "$Date$" + revision: "$Revision$" + +class + CMS_LOWER_UPPER_PAGER + +inherit + WSF_WIDGET_PAGER + +create + make + +end diff --git a/src/support/cms_ordered_pagination.e b/src/persistence/cms_data_query_parameters.e similarity index 61% rename from src/support/cms_ordered_pagination.e rename to src/persistence/cms_data_query_parameters.e index 42c5f3c..a333797 100644 --- a/src/support/cms_ordered_pagination.e +++ b/src/persistence/cms_data_query_parameters.e @@ -1,19 +1,36 @@ note - description: "Pagination parameters with order capability" + description: "[ + Parameters associated with data query. + It could be query over http, or storage. + ]" date: "$Date$" revision: "$Revision$" class - CMS_ORDERED_PAGINATION - -inherit - CMS_PAGINATION + CMS_DATA_QUERY_PARAMETERS create make - + +feature {NONE} -- Initialization + + make (a_offset: NATURAL; a_size: NATURAL) + do + offset := a_offset + size := a_size + ensure + size_set: size = a_size + offset_set: offset = a_offset + end + feature -- Access + size: NATURAL assign set_size + -- Number of items per page. + + offset: NATURAL assign set_offset + -- lower index of `items' pagination. + order_by: detachable READABLE_STRING_8 -- field to order by. @@ -22,6 +39,22 @@ feature -- Access feature -- Element change + set_size (a_size: NATURAL) + -- Set `size' with `a_size'. + do + size := a_size + ensure + size_set: size = a_size + end + + set_offset (a_offset: NATURAL) + -- Set offset with `a_offset'. + do + offset := a_offset + ensure + limit_set: offset = a_offset + end + set_ascending_order_by_field (a_field: detachable READABLE_STRING_8) -- Pager with a order_by `a_field' asc. do diff --git a/src/persistence/sql/cms_storage_sql_i.e b/src/persistence/sql/cms_storage_sql_i.e index 7e91029..8f38ab0 100644 --- a/src/persistence/sql/cms_storage_sql_i.e +++ b/src/persistence/sql/cms_storage_sql_i.e @@ -217,6 +217,21 @@ feature -- Access deferred end + sql_read_natural_64 (a_index: INTEGER): NATURAL_64 + -- Retrieved value at `a_index' position in `item'. + local + l_item: like sql_item + do + l_item := sql_item (a_index) + if attached {NATURAL_64} l_item as i then + Result := i + elseif attached {NATURAL_64_REF} l_item as l_value then + Result := l_value.item + else + Result := sql_read_integer_64 (a_index).to_natural_64 + end + end + sql_read_integer_64 (a_index: INTEGER): INTEGER_64 -- Retrieved value at `a_index' position in `item'. local diff --git a/src/service/cms_api_options.e b/src/service/cms_api_options.e index 2ce3f29..ec00e2a 100644 --- a/src/service/cms_api_options.e +++ b/src/service/cms_api_options.e @@ -14,4 +14,10 @@ create make, make_from_manifest +convert + make_from_manifest ({ ARRAY [TUPLE [key: STRING; value: detachable ANY]], + ARRAY [TUPLE [STRING_8, ARRAY [TUPLE [STRING_8, STRING_32]]]], + ARRAY [TUPLE [STRING_8, ARRAY [TUPLE [STRING_8, STRING_8]]]] + }) + end diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e index 0df5bf1..ca409a9 100644 --- a/src/service/response/cms_response.e +++ b/src/service/response/cms_response.e @@ -1065,6 +1065,9 @@ feature -- Generation l_is_active: BOOLEAN do create qs.make_from_string (request.percent_encoded_path_info) + if qs.starts_with ("/") then + qs.remove_head (1) + end l_is_active := qs.same_string (a_lnk.location) if not l_is_active then if attached request.query_string as l_query_string and then not l_query_string.is_empty then diff --git a/src/support/cms_pagination.e b/src/support/cms_pagination.e deleted file mode 100644 index 72fc688..0000000 --- a/src/support/cms_pagination.e +++ /dev/null @@ -1,50 +0,0 @@ -note - description: "Pagination parameters" - date: "$Date$" - revision: "$Revision$" - -class - CMS_PAGINATION - -create - make - -feature {NONE} -- Initialization - - make (a_offset: NATURAL; a_size: NATURAL) - do - offset := a_offset - size := a_size - ensure - size_set: size = a_size - offset_set: offset = a_offset - end - -feature -- Access - - size: NATURAL assign set_size - -- Number of items per page. - - offset: NATURAL assign set_offset - -- lower index of `items' pagination. - -feature -- Element change - - set_size (a_size: NATURAL) - -- Set `size' with `a_size'. - do - size := a_size - ensure - size_set: size = a_size - end - - set_offset (a_offset: NATURAL) - -- Set offset with `a_offset'. - do - offset := a_offset - ensure - limit_set: offset = a_offset - end - - -end diff --git a/src/support/cms_pagination_generator.e b/src/support/cms_pagination_generator.e new file mode 100644 index 0000000..ef2019c --- /dev/null +++ b/src/support/cms_pagination_generator.e @@ -0,0 +1,287 @@ +note + description: "Pagination class to generate html pagination links and header summary." + date: "$Date$" + revision: "$Revision$" + +class + CMS_PAGINATION_GENERATOR + +create + make + +feature {NONE} -- Initialization + + make (a_resource: READABLE_STRING_8; a_count: NATURAL_64; a_page_size: NATURAL) + -- Create an object with a pages of size `a_page_size'. + -- If `a_page_size' is zero, use default pagination size. + require + a_page_size > 0 + do + create query_parameters.make (0, 25) + + create resource.make (a_resource) + set_page_size (a_page_size) + set_upper (a_count) + set_current_page_index (1) + + maximum_ith_page_links := 7 + page_parameter_id := "page" + size_parameter_id := "size" + set_first_text_id ("<<") + set_prev_text_id ("<") + set_next_text_id (">") + set_last_text_id (">>") + end + +feature -- Access + + resource: URI_TEMPLATE + -- Resource associated with current pager. + + page_size: NATURAL + -- Number of items per page. + do + Result := query_parameters.size + end + + upper: NATURAL_64 + -- number of items. + -- if zero, no upper limit. + + current_page_index: INTEGER + -- Current page index. + + query_parameters: CMS_DATA_QUERY_PARAMETERS + -- Parameter for the associated query/resource. + +feature -- Status report + + has_upper_limit: BOOLEAN + -- Upper limit known? + do + Result := upper > 0 + end + + pages_count: INTEGER + -- Number of pages. + -- If upper is + require + has_upper_limit: has_upper_limit + do + Result := (upper // page_size.as_natural_64).to_integer_32 + if upper \\ page_size.to_natural_64 > 0 then + Result := Result + 1 + end + end + +feature -- Parameters + + page_parameter_id: STRING + -- Parameter id for page value. + + size_parameter_id: STRING + -- Parameter id for size value. + + maximum_ith_page_links: INTEGER + -- Maximum number of numeric ith page link. + -- ex: max = 6 gives "1 2 3 4 5 6 ... > >>". + + label_first: IMMUTABLE_STRING_32 + label_previous: IMMUTABLE_STRING_32 + label_next: IMMUTABLE_STRING_32 + label_last: IMMUTABLE_STRING_32 + +feature -- Element change + + set_page_size (a_size: NATURAL) + -- Set `page_size' to `a_size'. + do + query_parameters.set_size (a_size) + end + + set_upper (a_upper: NATURAL_64) + -- Set pages count, or upper limit `upper' to `a_size'. + do + upper := a_upper + end + + set_current_page_index (a_page_index: like current_page_index) + -- Set Current page index to `a_page_index'. + do + current_page_index := a_page_index + if a_page_index > 1 then + query_parameters.set_offset ((a_page_index - 1).to_natural_32 * page_size) + else + query_parameters.set_offset (0) + end + end + + set_page_parameter_id (a_id: READABLE_STRING_8) + -- Set "page" query parameter to `a_id'. + do + page_parameter_id := a_id + end + + set_size_parameter_id (a_id: READABLE_STRING_8) + -- Set "size" query parameter to `a_id'. + do + size_parameter_id := a_id + end + + get_setting_from_request (req: WSF_REQUEST) + -- Get various pager related settings from request `req' query paramenters. + -- Using `page_parameter_id' and `size_parameter_id' value for parameter names. + do + -- Size + if + attached {WSF_STRING} req.query_parameter (size_parameter_id) as l_size and then + attached l_size.value as l_value and then + l_value.is_natural + then + set_page_size (l_value.to_natural_32) + else + -- Keep default size + end + + -- Page + if + attached {WSF_STRING} req.query_parameter (page_parameter_id) as l_page and then + l_page.is_integer + then + set_current_page_index (l_page.integer_value) + else + set_current_page_index (1) + end + end + + set_first_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "First" link to `s'. + -- default: "<<" + do + create label_first.make_from_string_general (s) + end + + set_prev_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "Prev" link to `s'. + -- default: "<" + do + create label_previous.make_from_string_general (s) + end + + set_next_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "Next" link to `s'. + -- default: ">" + do + create label_next.make_from_string_general (s) + end + + set_last_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "Last" link to `s'. + -- default: ">>" + do + create label_last.make_from_string_general (s) + end + + set_maximum_ith_page_links (nb: INTEGER) + -- Set `maximum_ith_page_links' to `nb'. + do + maximum_ith_page_links := nb + end + +feature -- Conversion + + pagination_links: ARRAYED_LIST [CMS_LOCAL_LINK] + -- CMS local links related to Current paginations. + local + lnk: CMS_LOCAL_LINK + tb: HASH_TABLE [detachable ANY, STRING_8] + curr, max: INTEGER + i,j: INTEGER + do + create Result.make (maximum_ith_page_links) + + curr := current_page_index + if has_upper_limit then + max := pages_count + else + max := curr + page_size.to_integer_32 + end + + create tb.make (2) + tb.force (page_size, size_parameter_id) + tb.force (1, page_parameter_id) + if curr > 1 then + create lnk.make (label_first, resource.expanded_string (tb)) + Result.force (lnk) + end + + if curr > 1 then + tb.force (curr - 1, "page") + create lnk.make (label_previous, resource.expanded_string (tb)) + Result.force (lnk) + end + from + if curr >= maximum_ith_page_links // 2 then + i := curr - (maximum_ith_page_links // 2) + else + i := 1 + end + j := 0 + until + j >= maximum_ith_page_links or (has_upper_limit and then i > max) + loop + tb.force (i, "page") + create lnk.make (i.out, resource.expanded_string (tb)) + lnk.set_is_active (i = curr) + Result.force (lnk) + j := j + 1 + i := i + 1 + end + if not has_upper_limit or else i < max then + tb.force (i, "page") + create lnk.make ("...", resource.expanded_string (tb)) + Result.force (lnk) + end + + if curr < max then + tb.force (curr + 1, "page") + create lnk.make (label_next, resource.expanded_string (tb)) + Result.force (lnk) + end + + if upper > 0 and curr /= max then + tb.force (max, "page") + create lnk.make (label_last, resource.expanded_string (tb)) + Result.force (lnk) + end + end + +feature -- Convertion + + append_to_html (a_response: CMS_RESPONSE; a_output: STRING) + -- Append html pager to `a_output' in the context of `a_response'. + -- note: First, [Prev], [Next], Last. + local + lnk: CMS_LOCAL_LINK + do + a_output.append ("
    %N") + across + pagination_links as ic + loop + lnk := ic.item + if lnk.is_active then + a_output.append ("
  • ") + elseif lnk.title.same_string (label_previous) then + a_output.append ("
  • ") + elseif lnk.title.same_string (label_next) then + a_output.append ("
  • ") + else + a_output.append ("
  • ") + end + a_output.append (a_response.link (lnk.title, lnk.location, Void)) + a_output.append ("
  • ") + end + a_output.append ("
") + end + +end