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

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