The following example we want to render is set of cards using bootstrap like in the example Clash of Clans Cards using a database set and a FreeMarker template.

1 Script example
Copy
/** * Uses a database table and a Freemarker template to reproduce * CodePen "Clash of Clans Cards" example: * * https://codepen.io/drehimself/pen/QNXpyp * * Notice that access to template variables using $ must be * escaped (\$) cuase we are placing the freemarker html code * in a javascript text using temple strings (`sss`) and this * makes $ to be processed by javascript template engine. So * to protect $ for freemarker we need to escape it. */ Ax.db.execute("DROP TABLE IF EXISTS clash_of_clans"); Ax.db.execute(` CREATE TABLE clash_of_clans( name CHAR(20) NOT NULL, title CHAR(50) NOT NULL, level INTEGER NOT NULL, sup CHAR(1) NOT NULL, training INTEGER NOT NULL, speed INTEGER NOT NULL, cost INTEGER NOT NULL, top INTEGER NOT NULL, left INTEGER NOT NULL, bg_color CHAR(8) NOT NULL, border_color CHAR(8) NOT NULL, bg_image_url VARCHAR(255) NOT NULL, fg_image_url VARCHAR(255) NOT NULL, text LVARCHAR(512) ); `); Ax.db.execute(` INSERT INTO clash_of_clans VALUES("barbarian", "The Barbarian", 4, "S", 20, 16, 150, -65, -70, "#EC9B3B", "#BD7C2F", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/barbarian-bg.jpg", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/barbarian.png", "The Barbarian is a kilt-clad Scottish warrior with an angry, battle-ready expression, hungry for destruction. He has Killer yellow horseshoe mustache."); INSERT INTO clash_of_clans VALUES("archer", "The Archer", 5, "S", 25, 24, 300, -34, -37, "#EE5487", "#D04976", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/archer-bg.jpg", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/archer.png", "The Archer is a female warrior with sharp eyes. She wears a short, light green dress, a hooded cape, a leather belt and an attached small pouch."); INSERT INTO clash_of_clans VALUES("giant", "The Giant", 5, "M", 2, 12, 2250, -30, -25, "#F6901A", "#de7b09", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/giant-bg.jpg", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/giant.png", "Slow, steady and powerful, Giants are massive warriors that soak up huge amounts of damage. Show them a turret or cannon and you'll see their fury unleashed!"); INSERT INTO clash_of_clans VALUES("goblin", "The Goblin", 5, "S", 30, 32, 100, -21, -37, "#82BB30", "#71a32a", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/goblin-bg.jpg", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/goblin.png", "These pesky little creatures only have eyes for one thing: LOOT! They are faster than a Spring Trap, and their hunger for resources is limitless."); INSERT INTO clash_of_clans VALUES("wizard", "The Wizard", 6, "M", 5, 16, 4000, -28, -10, "#4FACFF", "#309eff", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/archer-bg.jpg", "https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/wizard.png", "The Wizard is a terrifying presence on the battlefield. Pair him up with some of his fellows and cast concentrated blasts of destruction on anything, land or sky!"); `); /** * Create a template for freemarker using the HTML */ /** * Create a template for freemarker using the HTML */ var fm = new Ax.freemarker.Template(` <!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- JQUERY --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js" crossorigin="anonymous"></script> <!-- SLICK --> <script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js" crossorigin="anonymous"></script> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick-theme.css" rel="stylesheet" crossorigin="anonymous"> <title>Clash of Clans</title> <style type="text/css"> /* ==================================================================== START OF CSS ==================================================================== */ @import url(https://fonts.googleapis.com/css?family=Lato:400,700,900); *, *:before, *:after { box-sizing: border-box; } body { background: linear-gradient(to bottom, #8c7a7a 0%, #af877c 65%, #af877c 100%) fixed; background: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/coc-background.jpg") no-repeat center center fixed; background-size: cover; font: 14px/20px "Lato", Arial, sans-serif; color: #9E9E9E; margin-top: 30px; } .slide-container { margin: auto; width: 600px; text-align: center; } .wrapper { padding-top: 40px; padding-bottom: 40px; } .wrapper:focus { outline: 0; } .clash-card { background: white; width: 300px; display: inline-block; margin: auto; border-radius: 19px; position: relative; text-align: center; box-shadow: -1px 15px 30px -12px black; z-index: 9999; } .clash-card__image { position: relative; height: 230px; margin-bottom: 35px; border-top-left-radius: 14px; border-top-right-radius: 14px; } .clash-card__level { text-transform: uppercase; font-size: 12px; font-weight: 700; margin-bottom: 3px; } .clash-card__unit-name { font-size: 26px; color: black; font-weight: 900; margin-bottom: 5px; } .clash-card__unit-description { padding: 20px; margin-bottom: 10px; } .clash-card__unit-stats { color: white; font-weight: 700; border-bottom-left-radius: 14px; border-bottom-right-radius: 14px; } .clash-card__unit-stats .one-third { width: 33%; float: left; padding: 20px 15px; } .clash-card__unit-stats sup { position: absolute; bottom: 4px; font-size: 45%; margin-left: 2px; } .clash-card__unit-stats .stat { position: relative; font-size: 24px; margin-bottom: 10px; } .clash-card__unit-stats .stat-value { text-transform: uppercase; font-weight: 400; font-size: 12px; } .clash-card__unit-stats .no-border { border-right: none; } .clearfix:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; } .slick-prev { left: 100px; z-index: 999; } .slick-next { right: 100px; z-index: 999; } /* ==================================================================== START OF FTL TEMPLATE ==================================================================== */ <#list rs as row> .clash-card__image--\${row["name"]} { background: url("\${row["bg_image_url"]}"); } .clash-card__image--\${row["name"]} img { width: 400px; position: absolute; top: \${row["top"]}px; left: \${row["left"]}px; } .clash-card__level--\${row["name"]} { color: \${row["bg_color"]}; } .clash-card__unit-stats--\${row["name"]} { background:\${row["bg_color"]}; } .clash-card__unit-stats--\${row["name"]} .one-third { border-right: 1px solid \${row["border_color"]}; } </#list> </style> <!-- Option 1: Bootstrap Bundle with Popper --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </head> <body> <div class="slide-container"> <#list rs as row> <div class="wrapper"> <div class="clash-card barbarian"> <div class="clash-card__image clash-card__image--barbarian"> <img src="\${row["fg_image_url"]}" alt="\${row["name"]}" /> </div> <div class="clash-card__level clash-card__level--\${row["name"]}">Level \${row["training"]}</div> <div class="clash-card__unit-name">\${row["title"]}</div> <div class="clash-card__unit-description"> \${row["text"]} </div> <div class="clash-card__unit-stats clash-card__unit-stats--\${row["name"]} clearfix"> <div class="one-third"> <div class="stat">\${row["training"]}<sup>\${row["sup"]}</sup></div> <div class="stat-value">Training</div> </div> <div class="one-third"> <div class="stat">\${row["speed"]}</div> <div class="stat-value">Speed</div> </div> <div class="one-third no-border"> <div class="stat">\${row["cost"]}</div> <div class="stat-value">Cost</div> </div> </div> </div> <!-- end clash-card barbarian--> </div> <!-- end wrapper --> </#list> </div> <!-- end container --> <script> (function() { var slideContainer = $('.slide-container'); slideContainer.slick(); $('.clash-card__image img').hide(); $('.slick-active').find('.clash-card img').fadeIn(200); // On before slide change slideContainer.on('beforeChange', function(event, slick, currentSlide, nextSlide) { $('.slick-active').find('.clash-card img').fadeOut(1000); }); // On after slide change slideContainer.on('afterChange', function(event, slick, currentSlide) { $('.slick-active').find('.clash-card img').fadeIn(200); }); })(); </script> </body> </html> `); /** * ResultSet must be scrollable as we will iterate it twice in the template */ var rs = Ax.db.executeScrollableQuery("SELECT * FROM clash_of_clans"); var html = fm.process("rs", rs); new Ax.io.File("/tmp/clash_of_clans.html").write(html);