TyranoScript Tutorial Part 6: Page Creation
/ 4 min read
One day, my boss said we needed a brand new UI, but luckily, I was prepared for it.
I’ve complained before that writing settings, CG, and other pages using TyranoScript is hard to understand, and it’s difficult to manage the page hierarchy. It would be better to just write it in HTML. So today, let’s analyze how to create a new page using HTML.
We’ll start with an existing “non-script” page, such as the default Load page, which can be found by doing a global search for displayLoad
in the kag.menu.js file.
this.kag.html("load", { array_save: array, novel: $.novel }, function (html_str) { var layer_menu = that.kag.layer.getMenuLayer(); var j_save = $(html_str); j_save.find(".save_list").css("font-family", that.kag.config.userFace); j_save.find(".save_display_area").each(function () { $(this).click(function (e) { var num = $(this).attr("data-num"); that.snap = null; that.loadGame(num); var layer_menu = that.kag.layer.getMenuLayer(); layer_menu.hide(); layer_menu.empty(); var layer_title = that.kag.layer.getTitleLayer(); layer_title.hide(); layer_title.empty(); if (that.kag.stat.visible_menu_button == true) $(".button_menu").show(); }); }); j_save.find(".button_smart").hide(); if ($.userenv() != "pc") { j_save.find(".button_smart").show(); j_save.find(".button_arrow_up").click(function () { var now = j_save.find(".area_save_list").scrollTop(); var pos = now - 160; layer_menu.find(".area_save_list").animate({ scrollTop: pos }, { queue: false }); }); j_save.find(".button_arrow_down").click(function () { var now = j_save.find(".area_save_list").scrollTop(); var pos = now + 160; j_save.find(".area_save_list").animate({ scrollTop: pos }, { queue: false }); }); } that.setMenu(j_save);});
The core of creating a new page is the kag.html
function, which can be found in kag.js:
{ html: function(html_file_name, data, callback) { var that = this data = data || {} if (this.cache_html[html_file_name]) { if (callback) { var tmpl = $.templates(this.cache_html[html_file_name]) var html = tmpl.render(data) callback($(html)) } } else { if (!this.kag.stat.sysview) { this.kag.stat.sysview = { save: './tyrano/html/save.html', load: './tyrano/html/load.html', backlog: './tyrano/html/backlog.html', menu: './tyrano/html/menu.html', } } var path_html = this.kag.stat.sysview[html_file_name] $.loadText(path_html, function(text_str) { var tmpl = $.templates(text_str) var html = tmpl.render(data) that.cache_html[html_file_name] = text_str if (callback) callback($(html)) }) } }}
The parameters of the html function are:
- File name
- Data passed in
- Callback function
Observing displayLoad
, it can be seen that loading the load
page requires passing the page name load
, an object containing archived content, and a callback function with HTML file content as a parameter. There is a flaw here, as the $(html)
passed into the callback is not simply a “str” but an object processed by jQuery.
In the html function, $.loadText
is used to fetch the local html file using Ajax, while functions such as $.templates
and tmpl.render
come from the open-source rendering engine jsrender.
In the load.html, we can see the use of a template:
<div class="save_list"> {{for array_save}} <div class="save_display_area save_list_item" data-num="{{:num}}"> <span class="save_list_item_thumb"> {{if img_data != ""}} <img class="pic" src="{{:img_data}}" /> {{/if}} </span> <span class="save_list_item_thumb"> {{if img_data == ""}} <div class="pic">No data</div> {{/if}} </span>
<div class="save_list_item_area"> <div class="save_list_item_date">{{:save_date}}</div> <div class="save_list_item_text">{{:title}}</div> </div> </div> {{/for}}</div>
However, I don’t intend to use jsrender as a template engine because I also want to incorporate Vue and take advantage of MVVM conveniently.
So, we can rewrite a simpler html
function:
{ htmlPure: function(html_file_name, data, callback) { var that = this data = data || {} if (this.cache_html[html_file_name]) { if (callback) { callback(this.cache_html[html_file_name]) } } else { var path_html = this.kag.stat.sysview[html_file_name] $.loadText(path_html, function(text_str) { that.cache_html[html_file_name] = text_str if (callback) callback(text_str) }) } },}
The htmlPure
function eliminates the template engine rendering and directly passes the html string to the callback function. (You can choose to keep jsrender, but in order to avoid conflicts with Vue’s template, you need to modify Vue’s delimiters)
After adding the htmlPure
function, we also need to create a new tag for creating the new page, which is named showExtendPage
:
tyrano.plugin.kag.tag.showExtendPage = { pm: {}, start: function (pm) { var that = this; this.kag.stat.is_skip = false; this.kag.htmlPure(pm.name, null, function (html_str) { var extendPage = $(html_str); var layer_extend = that.kag.layer.layer_extend; layer_extend[0].style.zIndex = pm.zindex || 9999999999; layer_extend[0].innerHTML = ""; layer_extend.fadeIn(); layer_extend.append(extendPage); }); this.kag.ftag.nextOrder(); },};
This is the approach to using custom pages. After replacing the script file with an html file, I felt liberated as I no longer need to worry about script callback navigation and hierarchy clearing, just call the showExtendPage tag to fade the page in.