1/* Part of ClioPatria SeRQL and SPARQL server 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2010-2018, VU University Amsterdam 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(html_basics, 36 [ hidden//2, % +Name, +Value 37 form_input//2, % +Label, +Input 38 form_submit//1, % +Label 39 n//2, % +Format, +Value 40 nc//2, % +Format, +Value 41 nc//3, % +Format, +Value, +Options 42 odd_even_row//3, % +Row, -Next, :Content 43 sort_th//3, % +Field, +ByNow, :Content 44 insert_html_file//1 % +FileSpec 45 ]). 46:- use_module(library(http/html_write)). 47:- use_module(library(sgml)). 48:- use_module(library(lists)). 49:- use_module(library(option)). 50:- use_module(library(occurs)). 51:- use_module(library(http/http_dispatch)). 52:- use_module(library(http/http_wrapper)). 53 54:- html_meta(( 55 form_input( , , , ), 56 odd_even_row( , , , , ), 57 sort_th( , , , , ))). 58 59/** <module> Simple Small HTML components 60*/ 61 62 /******************************* 63 * FORMS * 64 *******************************/ 65 66%! hidden(+Name, +Value)// is det. 67% 68% Create a hidden input field with given name and value 69 Name, Value) (--> 71 html(input([ type(hidden), 72 name(Name), 73 value(Value) 74 ])). 75 76 77%! form_input(+Label, +Input)// is det. 78%! form_submit(+Label)// is det. 79% 80% Building blocks for HTML forms. The form itself is a two-column 81% table of class =form= with labels at the left and inputs at the 82% right. These rules create rows for input and submit. 83 84form_input(Label, Input) --> 85 html(tr([ th(class(label), Label), 86 td(Input) 87 ])). 88 89 90form_submit(Label) --> 91 html(tr(class(buttons), 92 [ th([align(right), colspan(2)], 93 input([ type(submit), 94 value(Label) 95 ])) 96 ])). 97 98 99 /******************************* 100 * TABLES * 101 *******************************/ 102 103%! nc(+Format, +Value)// is det. 104%! nc(+Format, +Value, +Options)// is det. 105% 106% Numeric cell. The value is formatted using Format and 107% right-aligned in a table cell (td). 108% 109% @param Format is a (numeric) format as described by format/2 or 110% the constant =human=. _Human_ formatting applies to 111% integers and prints then in abreviated (K,M,T) form, 112% e.g., 4.5M for 4.5 million. 113% @param Options is passed as attributed to the =td= element. 114% Default alignment is =right=. 115 116nc(Fmt, Value) --> 117 nc(Fmt, Value, []). 118 119nc(Fmt, Value, Options) --> 120 { class(Value, Class), 121 merge_options(Options, 122 [ align(right), 123 class(Class) 124 ], Opts), 125 number_html(Fmt, Value, HTML) 126 }, 127 html(td(Opts, HTML)). 128 129class(Value, Class) :- 130 ( integer(Value) 131 -> Class = int 132 ; float(Value) 133 -> Class = float 134 ; Class = value 135 ). 136 137 138%! odd_even_row(+Row, -Next, :Content)// 139% 140% Create odd/even alternating table rows from a DCG. 141 142odd_even_row(Row, Next, Content) --> 143 { ( Row mod 2 =:= 0 144 -> Class = even 145 ; Class = odd 146 ), 147 Next is Row+1 148 }, 149 html(tr(class(Class), Content)). 150 151%! sort_th(+Field, +ByNow, :Label) 152% 153% Provide a column-header for a table that can be resorted. This 154% call creates a =th= element holding an =a=. The =a= has either 155% CSS class =sorted= if the column is sorted or =resort= if the 156% column can be sorted on this column. The use of this component 157% demands that the handler processes the parameter =sort_by= using 158% the field-name as argument. 159% 160% @param Field is the field-name that describes the sort on this 161% column. 162% @param ByNow is the field on which the table is currently 163% sorted. 164% @param Label is the label of the =a= element 165 166sort_th(Name, Name, Label) --> 167 html(th(a([class(sorted)], Label))). 168sort_th(Name, _By, Label) --> 169 { http_current_request(Request), 170 http_reload_with_parameters(Request, [sort_by(Name)], HREF) 171 }, 172 html(th(a([href(HREF), class(resort)], Label))). 173 174 175 /******************************* 176 * NUMBERS * 177 *******************************/ 178 179%! n(+Format, +Value)// 180% 181% HTML component to emit a number. 182% 183% @see nc//2 for details. 184 185n(Fmt, Value) --> 186 { number_html(Fmt, Value, HTML) }, 187 html(HTML). 188 189number_html(human, Value, HTML) :- 190 integer(Value), 191 !, 192 human_count(Value, HTML). 193number_html(Fmt, Value, HTML) :- 194 number(Value), 195 !, 196 HTML = Fmt-[Value]. 197number_html(_, Value, '~p'-[Value]). 198 199 200human_count(Number, HTML) :- 201 Number < 1024, 202 !, 203 HTML = '~d'-[Number]. 204human_count(Number, HTML) :- 205 Number < 1024*1024, 206 !, 207 KB is Number/1024, 208 digits(KB, N), 209 HTML = '~*fK'-[N, KB]. 210human_count(Number, HTML) :- 211 Number < 1024*1024*1024, 212 !, 213 MB is Number/(1024*1024), 214 digits(MB, N), 215 HTML = '~*fM'-[N, MB]. 216human_count(Number, HTML) :- 217 TB is Number/(1024*1024*1024), 218 digits(TB, N), 219 HTML = '~*fG'-[N, TB]. 220 221digits(Count, N) :- 222 ( Count < 100 223 -> N = 1 224 ; N = 0 225 ). 226 227 228 /******************************* 229 * INCLUDE FILES * 230 *******************************/ 231 232%! insert_html_file(+Specification)// 233% 234% Insert the content of an HTML file into the current document. 235% Only the content of the =body= element is included. 236 237insert_html_file(Alias) --> 238 { absolute_file_name(Alias, Page, [access(read)]), 239 load_html_file(Page, DOM), 240 contains_term(element(body, _, Body), DOM), 241 Style = element(style, _, _), 242 findall(Style, sub_term(Style, DOM), Styles), 243 append(Styles, Body, Content) 244 }, 245 html(Content)