1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: jan@swi-prolog.org 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2024, SWI-Prolog Solutions b.v. 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(htmx, 36 [ reply_htmx/1, % +HTML 37 reply_htmx/2, % +HTML, +Request 38 htmx_oob//2 % ++Id, :HTML 39 ]). 40:- use_module(library(http/html_write)). 41 42/** <module> Support htmx.org 43 44Quoted from htmx.org: 45 46> [htmx](https://htmx.org) gives you access to AJAX, CSS Transitions, 47> WebSockets and Server Sent Events directly in HTML, using attributes, 48> so you can build modern user interfaces with the simplicity and power 49> of hypertext 50 51The idea behind htmx is to allow adding attributes to any HTML element 52that cause an HTTP request. The HTTP response is typically a (short) 53HTML fragment that extends or replaces an element on the page. This 54allows us to program a most functionality interactive seen in modern web 55applications using the powerful SWI-Prolog HTML generation framework 56rather than having to write a JSON backend and accompanying JavaScript 57frontend that runs in the browser. 58 59Below is a minimal, yet fully functional application 60 61``` 62:- use_module(library(http/http_server)). 63:- use_module(library(http/htmx)). 64:- use_module(library(main)). 65 66:- initialization(main, main). 67 68main(_Argv) :- 69 http_server([port(8080)]), 70 thread_get_message(quit). 71 72http:location(htmx, root(htmx), []). 73 74:- http_handler(root(.), home, []). 75 76home(_Request) :- 77 reply_html_page( 78 [ title('HTMX demo'), 79 script(src('https://unpkg.com/htmx.org'), []) 80 ], 81 [ button([ 'hx-post'('/htmx/clicked'), 82 'hx-swap'('outerHTML') 83 ], 84 'Click me') 85 ]). 86 87:- http_handler(htmx(clicked), reply_htmx(\clicked), []). 88 89clicked --> 90 html('Thanks for clicking me!'). 91``` 92 93HTMX requires no dedicated support from the server. This library 94provides reply_htmx/1,2 to reply with a single HTML element rather than 95an entire page. Future versions of this library may provide some 96additional utility predicates. 97*/ 98 99:- html_meta 100 reply_htmx( ), 101 reply_htmx( , ), 102 htmx_oob( , , , ). 103 104%! reply_htmx(+HTML) is det. 105%! reply_htmx(+HTML, +Request) is det. 106% 107% Reply a plain HTML element as opposed to a complete HTML page as 108% created using reply_html_page/2,3. While reply_htmx/1 is to be used 109% in a normal HTTP handler (route), reply_htmx/2 may be registered 110% directly in the http_handler/3 declaration to deal with simple cases 111% where we do not need the `Request` data. 112 113reply_htmx(HTML) :- 114 phrase(html(HTML), Tokens), 115 format('Content-type: text/html~n~n', []), 116 print_html(Tokens). 117 118reply_htmx(HTML, _Request) :- 119 reply_htmx(HTML). 120 121%! htmx_oob(++Target, :HTML)// is det. 122% 123% Emit an htmx out-of-band element. HTML is used to swap the 124% content of the DOM element with id Target. 125 126htmx_oob(Target, HTML) --> 127 html(div([id(Target), 'hx-swap-oob'(true)], 128 HTML))