No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ui.ts 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /// <reference path="./card.ts" />
  2. /// <reference path="./colors.ts" />
  3. /// <reference path="./icons.ts" />
  4. /// <reference path="./example_data.ts" />
  5. /// <reference path="./jquery.d.ts" />
  6. module RpgCardsUI {
  7. var deck: RpgCards.CardDeck = null;
  8. var options: RpgCards.Options = null;
  9. var cardGenerator: RpgCards.CardHtmlGenerator = null;
  10. var pageGenerator: RpgCards.PageHtmlGenerator = null;
  11. // ============================================================================
  12. // Seleted card
  13. // ============================================================================
  14. function selected_card_index(): number {
  15. return parseInt($("#selected-card").val(), 10);
  16. }
  17. function selected_card(): RpgCards.Card {
  18. var index = selected_card_index();
  19. if (deck.cards.length > index) {
  20. return deck.cards[index];
  21. } else {
  22. return null;
  23. }
  24. }
  25. function select_card_by_index(index: number) {
  26. if (index > -1) {
  27. $("#selected-card").val("" + index);
  28. } else {
  29. $("#selected-card").val("" + (deck.cards.length - 1));
  30. }
  31. update_selected_card();
  32. }
  33. function select_card_by_card(card: RpgCards.Card) {
  34. var index = deck.cards.indexOf(card);
  35. select_card_by_index(index);
  36. }
  37. // ============================================================================
  38. // Rendering
  39. // ============================================================================
  40. function render_selected_card() {
  41. var card = selected_card();
  42. $('#preview-container').empty();
  43. if (card) {
  44. var front = cardGenerator.card_front(card, options, " ");
  45. var back = cardGenerator.card_back(card, options, " ");
  46. $('#preview-container').html(front + "\n" + back);
  47. }
  48. }
  49. function update_selected_card() {
  50. var card = selected_card();
  51. if (card) {
  52. $("#card-title").val(card.title);
  53. $("#card-title-size").val(card.title_size);
  54. $("#card-title-icon-text").val(card.title_icon_text);
  55. $("#card-count").val(""+card.count);
  56. $("#card-icon").val(card.icon);
  57. $("#card-icon-back").val(card.icon_back);
  58. $("#card-contents").val(card.contents.join("\n"));
  59. $("#card-tags").val(card.tags.join(", "));
  60. $("#card-color").val(card.color).change();
  61. } else {
  62. $("#card-title").val("");
  63. $("#card-title-size").val("");
  64. $("#card-title-icon-text").val("");
  65. $("#card-count").val("1");
  66. $("#card-icon").val("");
  67. $("#card-icon-back").val("");
  68. $("#card-contents").val("");
  69. $("#card-tags").val("");
  70. $("#card-color").val("").change();
  71. }
  72. render_selected_card();
  73. }
  74. function update_card_list() {
  75. deck.commit();
  76. $("#total_card_count").text("Deck contains " + deck.cards.length + " unique cards.");
  77. $('#selected-card').empty();
  78. for (var i = 0; i < deck.cards.length; ++i) {
  79. var card = deck.cards[i];
  80. $('#selected-card')
  81. .append($("<option></option>")
  82. .attr("value", i)
  83. .text(card.title));
  84. }
  85. update_selected_card();
  86. }
  87. // ============================================================================
  88. // Color picker
  89. // ============================================================================
  90. function setup_color_selector() {
  91. // Insert colors
  92. $.each(card_colors, function (name, val) {
  93. $(".colorselector-data")
  94. .append($("<option></option>")
  95. .attr("value", name)
  96. .attr("data-color", val)
  97. .text(name));
  98. });
  99. // Callbacks for when the user picks a color
  100. (<any>$('#default_color_selector')).colorselector({
  101. callback: function (value, color, title) {
  102. $("#default-color").val(title);
  103. set_default_color(title);
  104. }
  105. });
  106. (<any>$('#card_color_selector')).colorselector({
  107. callback: function (value, color, title) {
  108. $("#card-color").val(title);
  109. set_card_color(value);
  110. }
  111. });
  112. (<any>$('#foreground_color_selector')).colorselector({
  113. callback: function (value, color, title) {
  114. $("#foreground-color").val(title);
  115. set_foreground_color(value);
  116. }
  117. });
  118. (<any>$('#background_color_selector')).colorselector({
  119. callback: function (value, color, title) {
  120. $("#background-color").val(title);
  121. set_background_color(value);
  122. }
  123. });
  124. // Styling
  125. $(".dropdown-colorselector").addClass("input-group-addon color-input-addon");
  126. }
  127. function set_card_color(value) {
  128. var card = selected_card();
  129. if (card) {
  130. card.color = value;
  131. render_selected_card();
  132. }
  133. }
  134. function set_default_color(color) {
  135. options.default_color = color;
  136. render_selected_card();
  137. }
  138. function set_foreground_color(color) {
  139. options.foreground_color = color;
  140. }
  141. function set_background_color(color) {
  142. options.background_color = color;
  143. }
  144. function update_card_color_selector(color, input, selector) {
  145. if ($(selector + " option[value='" + color + "']").length > 0) {
  146. // Update the color selector to the entered value
  147. (<any>$(selector)).colorselector("setValue", color);
  148. } else {
  149. // Unknown color - select a neutral color and reset the text value
  150. (<any>$(selector)).colorselector("setValue", "");
  151. input.val(color);
  152. }
  153. }
  154. // ============================================================================
  155. // Card values
  156. // ============================================================================
  157. function on_change_card_title() {
  158. var title = $("#card-title").val();
  159. var card = selected_card();
  160. if (card) {
  161. card.title = title;
  162. $("#selected-card option:selected").text(title);
  163. render_selected_card();
  164. }
  165. }
  166. function on_change_card_color() {
  167. var input = $(this);
  168. var color = input.val();
  169. update_card_color_selector(color, input, "#card_color_selector");
  170. set_card_color(color);
  171. }
  172. function on_change_card_property() {
  173. var property = $(this).attr("data-property");
  174. var value = $(this).val();
  175. var card = selected_card();
  176. if (card) {
  177. card[property] = value;
  178. render_selected_card();
  179. }
  180. }
  181. function on_change_card_contents() {
  182. var value = $(this).val();
  183. var card = selected_card();
  184. if (card) {
  185. card.contents = value.split("\n");
  186. render_selected_card();
  187. }
  188. }
  189. function on_change_card_tags() {
  190. var value = $(this).val();
  191. var card = selected_card();
  192. if (card) {
  193. if (value.trim().length == 0) {
  194. card.tags = [];
  195. } else {
  196. card.tags = value.split(",").map(function (val) {
  197. return val.trim().toLowerCase();
  198. });
  199. }
  200. render_selected_card();
  201. }
  202. }
  203. // ============================================================================
  204. // Global default values
  205. // ============================================================================
  206. function on_change_option() {
  207. var property = $(this).attr("data-option");
  208. var value = $(this).val();
  209. options[property] = value;
  210. render_selected_card();
  211. }
  212. function on_change_default_color() {
  213. var input = $(this);
  214. var color = input.val();
  215. update_card_color_selector(color, input, "#default_color_selector");
  216. set_default_color(color);
  217. }
  218. function on_change_default_icon() {
  219. var value = $(this).val();
  220. options.default_icon = value;
  221. render_selected_card();
  222. }
  223. function on_change_default_title_size() {
  224. options.default_title_size = $(this).val();
  225. render_selected_card();
  226. }
  227. function on_change_default_icon_size() {
  228. options.icon_inline = $(this).is(':checked');
  229. render_selected_card();
  230. }
  231. // ============================================================================
  232. // Map/Filter
  233. // ============================================================================
  234. function apply_default_color() {
  235. deck.cards.forEach((card) => {
  236. card.color = options.default_color;
  237. });
  238. render_selected_card();
  239. }
  240. function apply_default_icon() {
  241. deck.cards.forEach((card) => {
  242. card.icon = options.default_icon;
  243. });
  244. render_selected_card();
  245. }
  246. function apply_default_icon_back() {
  247. deck.cards.forEach((card) => {
  248. card.icon_back = options.default_icon;
  249. });
  250. render_selected_card();
  251. }
  252. function sort() {
  253. showModal("#sort-modal");
  254. }
  255. function sort_execute() {
  256. hideModal("#sort-modal");
  257. var fn_code = $("#sort-function").val();
  258. var fn = new Function("card_a", "card_b", fn_code);
  259. deck.cards = deck.cards.sort(function (card_a, card_b) {
  260. var result = fn(card_a, card_b);
  261. return result;
  262. });
  263. update_card_list();
  264. }
  265. function filter() {
  266. showModal("#filter-modal");
  267. }
  268. function filter_execute() {
  269. hideModal("#filter-modal");
  270. var fn_code = $("#filter-function").val();
  271. var fn = new Function("card", "deck", fn_code);
  272. deck.cards.forEach((card) => {
  273. fn(card, deck);
  274. });
  275. deck.commit();
  276. update_card_list();
  277. }
  278. // ============================================================================
  279. // Modals
  280. // ============================================================================
  281. function showModal(id: string) {
  282. (<any>$(id)).modal('show');
  283. }
  284. function hideModal(id: string) {
  285. (<any>$(id)).modal('hide');
  286. }
  287. // ============================================================================
  288. // I/O
  289. // ============================================================================
  290. function save_file() {
  291. var str = JSON.stringify(deck.toJSON(), null, " ");
  292. var parts = [str];
  293. var blob = new Blob(parts, { type: 'application/json' });
  294. var url = URL.createObjectURL(blob);
  295. var a = <HTMLLinkElement>$("#file-save-link")[0];
  296. a.href = url;
  297. (<any>a).download = "rpg_cards.json";
  298. a.click();
  299. setTimeout(function () { URL.revokeObjectURL(url); }, 1000);
  300. }
  301. function load_sample() {
  302. deck = RpgCards.CardDeck.fromJSON(card_data_example);
  303. update_card_list();
  304. }
  305. function clear_all() {
  306. deck = new RpgCards.CardDeck();
  307. update_card_list();
  308. }
  309. function ui_load_files(evt) {
  310. // ui_clear_all();
  311. var files = evt.target.files;
  312. for (var i = 0, f; f = files[i]; i++) {
  313. var reader = new FileReader();
  314. reader.onload = function (reader) {
  315. var data = JSON.parse(this.result);
  316. var deck = RpgCards.CardDeck.fromJSON(data);
  317. add_cards(deck.cards);
  318. };
  319. reader.readAsText(f);
  320. }
  321. // Reset file input
  322. (<any>$("#file-load-form")[0]).reset();
  323. }
  324. function add_cards(cards: RpgCards.Card[]) {
  325. deck.addCards(cards);
  326. update_card_list();
  327. }
  328. function add_new_card() {
  329. deck.addNewCard();
  330. update_card_list();
  331. select_card_by_index(deck.cards.length - 1);
  332. }
  333. function duplicate_card() {
  334. var newCard = null;
  335. if (deck.cards.length > 0) {
  336. var old_card = selected_card();
  337. newCard = deck.duplicateCard(old_card);
  338. } else {
  339. newCard = deck.addNewCard();
  340. }
  341. update_card_list();
  342. select_card_by_card(newCard);
  343. }
  344. function delete_card() {
  345. var index = selected_card_index();
  346. var card = selected_card();
  347. deck.deleteCard(card);
  348. update_card_list();
  349. select_card_by_index(Math.min(index, deck.cards.length - 1));
  350. }
  351. // ============================================================================
  352. // Menu
  353. // ============================================================================
  354. function open_help() {
  355. showModal("#help-modal");
  356. }
  357. function select_icon() {
  358. window.open("http://game-icons.net/", "_blank");
  359. }
  360. var generate_modal_shown = false;
  361. function generate() {
  362. if (deck.cards.length === 0) {
  363. alert("Your deck is empty. Please define some cards first, or load the sample deck.");
  364. return;
  365. }
  366. // Generate output HTML
  367. var card_html = pageGenerator.generateHtml(deck.cards, options);
  368. // Open a new window for the output
  369. // Use a separate window to avoid CSS conflicts
  370. var tab = window.open("output.html", 'rpg-cards-output');
  371. if (generate_modal_shown == false) {
  372. showModal("#print-modal");
  373. generate_modal_shown = true;
  374. }
  375. // Send the generated HTML to the new window
  376. // Use a delay to give the new window time to set up a message listener
  377. setTimeout(function () { tab.postMessage(card_html, '*') }, 500);
  378. }
  379. // ============================================================================
  380. // Initialization
  381. // ============================================================================
  382. function init() {
  383. deck = new RpgCards.CardDeck();
  384. options = new RpgCards.Options();
  385. cardGenerator = new RpgCards.CardHtmlGenerator;
  386. pageGenerator = new RpgCards.PageHtmlGenerator;
  387. setup_color_selector();
  388. (<any>$('.icon-list')).typeahead({ source: icon_names });
  389. // Menu
  390. $("#sort-execute").click(sort_execute);
  391. $("#filter-execute").click(filter_execute);
  392. $("#button-generate").click(generate);
  393. $("#button-load").click(function () { $("#file-load").click(); });
  394. $("#file-load").change(ui_load_files);
  395. $("#button-clear").click(clear_all);
  396. $("#button-load-sample").click(load_sample);
  397. $("#button-save").click(save_file);
  398. $("#button-sort").click(sort);
  399. $("#button-filter").click(filter);
  400. $("#button-add-card").click(add_new_card);
  401. $("#button-duplicate-card").click(duplicate_card);
  402. $("#button-delete-card").click(delete_card);
  403. $("#button-help").click(open_help);
  404. $("#button-apply-color").click(apply_default_color);
  405. $("#button-apply-icon").click(apply_default_icon);
  406. $("#button-apply-icon-back").click(apply_default_icon_back);
  407. $("#selected-card").change(update_selected_card);
  408. $("#card-title").change(on_change_card_title);
  409. $("#card-title-size").change(on_change_card_property);
  410. $("#card-title-icon-text").change(on_change_card_property);
  411. $("#card-icon").change(on_change_card_property);
  412. $("#card-count").change(on_change_card_property);
  413. $("#card-icon-back").change(on_change_card_property);
  414. $("#card-color").change(on_change_card_color);
  415. $("#card-contents").change(on_change_card_contents);
  416. $("#card-tags").change(on_change_card_tags);
  417. // Global options
  418. $("#page-size").change(on_change_option);
  419. $("#page-rows").change(on_change_option);
  420. $("#page-columns").change(on_change_option);
  421. $("#card-arrangement").change(on_change_option);
  422. $("#card-size").change(on_change_option);
  423. $("#background-color").change(on_change_option);
  424. $("#default-color").change(on_change_default_color);
  425. $("#default-icon").change(on_change_default_icon);
  426. $("#default-title-size").change(on_change_default_title_size);
  427. $("#small-icons").change(on_change_default_icon_size);
  428. $(".icon-select-button").click(select_icon);
  429. update_card_list();
  430. }
  431. $(document).ready(function () {
  432. init();
  433. });
  434. }