暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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