「javascript/クエスト情報変換【タブ用】」の編集履歴(バックアップ)一覧に戻る

javascript/クエスト情報変換【タブ用】 - (2018/01/21 (日) 14:17:32) のソース

#js(){{{{{
<style type="text/css">
input[name="BOLD"]:checked + input {
	font-weight: bold;
}
select {
	padding: 3px 0px;
	vertical-align: bottom;
	margin: 1px;
}
input {
	padding: 3px 0px;
	margin: 1px 0px;
}
input[type="checkbox"],
label {
	cursor: pointer;
}
textarea {
	box-sizing: border-box;
	width: 100%;
	height: 50px;
	vertical-align: bottom;
	text-align: center;
}
.clearbtn,
.minibtn {
	padding: 0;
	min-width: 1.5em;
	margin: 3px;
}
</style>
<script type="text/javascript">

// テキストノード追加拡張
$.fn.appendText = function(text) {
	return this.each(function() {
		var textNode = document.createTextNode(text);
		$(this).append(textNode);
	});
};

var QuestGen = (function () {

	const defaults = {
		design: 0,
		max_wave: 9,
		max_phase: 9,
		max_support: 9,
		max_enemyleft: 9,
		max_enemyright: 9,
		bold_color: ["#e6e6fa","#bee0c2","#fddea5"],
		back_color: ["#f5fffa","#f5fffa","#f5fffa"],
		caption_color: ["#17184b","#004d25","#d3381c"],
		class_list: ['剣', '弓', '槍', '騎', '術', '殺', '狂', '盾', '裁', '讐', '月', '分', '獣', '失', '降', '?'],
	};
	
	/**
	* defaultsとインスタンスoptionsのマージ用(settings)
	* Merge two or more objects. Returns a new object.
	* @private
	* @param {Boolean}  deep	 If true, do a deep (or recursive) merge [optional]
	* @param {Object}   objects  The objects to merge together
	* @returns {Object}		  Merged values of defaults and options
	*/
	const extend = function ()  {

		let extended = {};
		let deep = false;
		let i = 0;
		let length = arguments.length;

		/* Check if a deep merge */
		if (Object["proto"+"type"].toString.call(arguments[0]) === "[object Boolean]") {
			deep = arguments[0];
			i++;
		}

		/* Merge the object into the extended object */
		let merge = function (obj) {
			for (let prop in obj) {
				if (Object["proto"+"type"].hasOwnProperty.call(obj, prop)) {
					/* If deep merge and property is an object, merge properties */
					if (deep && Object["proto"+"type"].toString.call(obj[prop]) === "[object Object]") {
						extended[prop] = extend(true, extended[prop], obj[prop]);
					} else {
						extended[prop] = obj[prop];
					}
				}
			}
		};

		/* Loop through each object and conduct a merge */
		for (; i < length; i++) {
			let obj = arguments[i];
			merge(obj);
		}

		return extended;
	};
	
	// C#風String.Format
	const Format = function(te, re) {
		if (typeof re != "object")
			re = Array["proto"+"type"].slice.call(arguments, 1);
		return te.replace(/{(\d+)}/g, function(m, c) {
			return (re[c] != null) ? re[c] : ' ';
		});
	};
	
	// 3桁区切り
	const toComma = function(num) {
		if (typeof(num) === 'undefined')
			return '';
		if (typeof(num) === 'string')
			num = parseInt(num);
		if (Number.isNaN(num))
			return '';
		return parseInt(num / 1000) == 0 ? num % 1000 : toComma(parseInt(num / 1000)) + ',' + ('000' + (num % 1000)).slice(-3);
	}

	function QuestGen(target, options) {
		this.settings = extend(defaults, options || {});
		this.target = target;
		this.init();
	}
	QuestGen["proto"+"type"] = {
		init: function() {
			this.phase = 1;
			this.tempClsSelect = $('<select>', {'name': 'SVTCLS'}).css('width', '3em').append($.map(this.settings.class_list, function(e) { return $('<option>').text(e); }));
			var self = this;
			this.tempClearBtn = $('<input>', {'type': 'button', 'data-target': 'tr'}).addClass('clearbtn').css('padding', '0').val('消').click(function() {
				let data = $(this).attr('data-target');
				self.clearInput(data ? $(this).parents(data) : $(this).parent());
			});
			this.setDesign(0);
		},
		getBg: function() { return this.settings.back_color[this.settings.design]; },
		getBold: function() { return this.settings.bold_color[this.settings.design]; },
		getCaption: function() { return this.settings.caption_color[this.settings.design]; },
		// テーブル色変更
		setDesign: function(num) {
			this.settings.design = num;
			$('style#design').remove();
			let style = '<style type="text/css" id="design">';
			style += '.phase td { background-color: ' + this.getBg() + '; text-align: center; }';
			style += '.headrow { background-color: '+ this.getCaption() +'!important; color: white; }';
			style += '.subrow { background-color: '+ this.getBold() +'!important; }';
			style += '</style>';
			$('head').append(style);
		},
		// ターゲット以下の入力欄を削除
		clearInput: function(tgt) {
			$('input[type="number"],input[type="text"]', tgt).val('');
			$('input[type="checkbox"]', tgt).prop('checked', false).change();
			$('select', tgt).prop('selectedIndex', 0).change();
		},
		// 入力欄を作成する
		makeTable: function() {
			let table = $('<table>', {'cellspacing': "1", 'border': "0"}).addClass('phase');
			table.append(this.makeHead());
			table.append(this.makeWaves());
			table.append(this.makeSupport());
			table.append(this.makeEnemy(true));
			table.append(this.makeEtc());
			table.appendTo(this.target);
		},
		// クエスト共通部分の作成
		makeHead: function() {
			let thead = $('.template thead').clone(true);
			thead.find('td:eq(0)').prepend(this.tempClearBtn.clone(true).attr('data-target', 'thead'));
			return thead;
		},
		// エネミー欄の作成
		makeEnemy: function(addcontrol) {
			let addcontrol = (addcontrol !== undefined) ? addcontrol : false;
			let tbody = $('<tbody>').addClass('enemydetail');
			var self = this;
			{
				let td = $('<td>', {'colspan': 4, 'class': 'subrow'});
				if (addcontrol) {
					let changeRowFunc = function() {
						let elems = $('.enemydetail', self.target);
						if ($(this).attr('name') == 'ADDROW') {
							$(elems[elems.length-1]).after(self.makeEnemy());
						} else if (elems.length > 1) {
							$(elems[elems.length-1]).remove();
						}
					};
					td.append($('<input>', {'type': 'button', 'name': 'SUBROW'}).addClass('minibtn').css('float', 'left').val('-').click(changeRowFunc));
					td.append($('<input>', {'type': 'button', 'name': 'ADDROW'}).addClass('minibtn').css('float', 'left').val('+').click(changeRowFunc));
				}
				this.tempClearBtn.clone(true).attr('data-target', 'tbody').prop('disabled', $('#clearLock').prop('checked') || false).appendTo(td);
				td.appendText('エネミー《');
				td.appendText('隠').append($('<input>', {'type': 'checkbox', 'name': 'HIDE'}));
				$('<input>', {'type': 'text', 'name': 'NAME'}).css('width', '12em').appendTo(td);
				td.appendText('》(左列行数:');
				let sel = $('<select>', {'name': 'LEFTNUM'}).css('width', '3em')
				.append($.map(Array.from({'length': this.settings.max_enemyleft+1}, (v, k) => k), function(e) { return $('<option>').text(e); }))
				.prop('selectedIndex', 0)
				.change(function() {
					let lines = $(this).parents('tbody').children('tr:nth-child(n+2)');
					var num = $(this).val() * self.settings.max_enemyright;
					lines.each(function(i, e) {
						if (num-- > 0)
							$(e).show();
						else
							$(e).hide();
					});
				}).appendTo(td);
				td.appendText(')【0=エネミー欄非表示】');
				tbody.append($('<tr>').append(td));
			}

			for (let i = 0; i < this.settings.max_enemyleft; i++) {
				let td = $('<td>', {'colspan': 2, 'rowspan': this.settings.max_enemyright})
				.append($('<input>', {'type': 'text', 'name': 'LEFTTEXT'}).css('width', '12em'))
				.append($('<br>'))
				.appendText('(右列行数');
				
				let rsel = $('<select>', {'name': 'RIGHTNUM'}).css('width', '3em')
				.append($.map(Array.from({'length': this.settings.max_enemyright}, (v, k) => k+1), function(e) { return $('<option>').text(e); }))
				.prop('selectedIndex', 0)
				.change(function() {
					let val = $(this).val();
					let cur = $(this).parents('tr');
					for (let n = 0; n < self.settings.max_enemyright; n++) {
						if (n < val) {
							cur.children('td:last-child').show();
						} else {
							cur.children('td:last-child').hide();
						}
						cur = cur.next();
					}
				}).appendTo(td);
				td.appendText(')');
				var tr = $('<tr>').hide().append(td);
				$('<td>', {'colspan': 2}).append($('<textarea>', {'name': 'RIGHTTEXT'})).appendTo(tr);
				tbody.append(tr);
				// 右列の処理(2こめ以降)
				let remain = this.settings.max_enemyright - 1;
				for (let r = 0; r < remain; r++) {
					tr = $('<tr>').hide();
					$('<td>', {'colspan': 2}).append($('<textarea>', {'name': 'RIGHTTEXT'})).hide().appendTo(tr);
					tbody.append(tr);
				}
			}
			return tbody;
		},
		// 備考欄の作成
		makeEtc: function() {
			let tbody = $('<tbody>');
			let td = $('<td>', {'colspan': 4, 'class': 'subrow'})
			.append(this.tempClearBtn.clone(true).attr('data-target', 'tbody'))
			.appendText('備考 (');
			
			$('<input>', {'type': 'checkbox', 'name': 'ETCON'}).change(function() {
				let tarea = $('textarea[name="TEXT"]', $(this).parents('tbody'));
				if ($(this).prop('checked'))
					tarea.show();
				else
					tarea.hide();
			}).appendTo(td);
			td.appendText('表示)');
			tbody.append($('<tr>').append(td));
			td = $('<td>', {'colspan': 4});
			$('<textarea>', {'name': 'TEXT'}).hide().appendTo(td);
			tbody.append($('<tr>').append(td));
			return tbody;
		},
		// 全WAVEの敵デッキの作成
		makeWaves: function(visible_count) {
			let visible_count = (visible_count !== undefined) ? visible_count : 3;
			let tbody = $('<tbody>').addClass('enemydecks');
			// ヘッダー欄
			{
				let tr = $('<tr>');
				let td = $('<td>', {'colspan': 2, 'class': 'subrow'});
				this.tempClearBtn.clone(true).attr('data-target', 'tbody').appendTo(td);
				$('<input>', {'type': 'text', 'name': 'QID'}).css('width', '5em').appendTo(td);
				td.appendText(' 全');
				let sel = $('<select>', {'name': 'WAVECOUNT'}).css('width', '3em');
				for (let i = 0; i < this.settings.max_wave+1; i++) {
					$('<option>').text(i).appendTo(sel);
				}
				sel.prop('selectedIndex', visible_count);
				var self = this;
				sel.change(function() {
					let val = parseInt($(this).val());
					$('.wave', tbody).each(function() {
						if (parseInt($(this).attr('data-wave')) <= val)
							$(this).show();
						else
							$(this).hide();
					});
				});
				sel.appendTo(td);
				td.appendText('【0=Battleなし】');
				tr.append(td);
				td = $('<td>', {'colspan': 2, 'class': 'subrow'});
				td.appendText('クラス構成');
				let ad = $('<label>(手動:<input type="checkbox" name="MANUALDETAIL">)</label>').appendTo(td);
				ad = ad.children('input');
				ad.change(function() {
					$(this).parent().next().prop('disabled', !$(this).prop('checked'));
				});
				$('<input>', {'type': 'text', 'name': 'DECKDETAIL'}).css('width', '15em').prop('disabled', true).appendTo(td);
				tbody.append(tr.append(td));
			}
			let unit = this.makeSvt();
			// 1WAVEのエネミー入力欄の増減
			let changeRowFunc = function() {
				let tr = $(this).parents('tr');
				let tr_end = tr;
				let current_wave = tr.attr('data-wave');
				let count = 0;
				for (let elem = tr; elem.length > 0 && elem.attr('data-wave') == current_wave; elem = elem.next()) {
					tr_end = elem;
					count++;
				}
				if ($(this).attr('name') == 'ADDROW') {
					tr.children('td:eq(0)').attr('rowspan', count+1);
					tr = $('<tr>').attr('data-wave', current_wave).addClass('wave');
					for (let j = 0; j < 3; j++) {
						unit.clone(true).appendTo(tr);
					}
					tr_end.after(tr);
				} else if (tr != tr_end) {
					tr.children('td:eq(0)').attr('rowspan', count-1);
					tr_end.remove();
				}
			};
			for (let i = 0; i < this.settings.max_wave; i++) {
				let tr = $('<tr>').attr('data-wave', i+1).addClass('wave').css('display', i < visible_count ? 'table-row' : 'none');
				$('<td>').text(i+1)
				.append(this.tempClearBtn.clone(true))
				.append($('<br>'))
				.append($('<input>', {'type': 'button', 'name': 'SUBROW'}).addClass('minibtn').val('-').click(changeRowFunc))
				.append($('<input>', {'type': 'button', 'name': 'ADDROW'}).addClass('minibtn').val('+').click(changeRowFunc))
				.appendTo(tr);
				for (let j = 0; j < 3; j++) {
					unit.clone(true).appendTo(tr);
				}
				tbody.append(tr);
			}
			return tbody;
		},
		// ユニット入力欄の生成
		makeSvt: function() {
			let td = $('<td>').addClass('unit');
			td.appendText('隠').append($('<input>', {'type': 'checkbox', 'name': 'HIDE'}));
			//td.appendText('太').append($('<input>', {'type': 'checkbox', 'name': 'BOLD'}));
			$('<input>', {'type': 'text', 'name': 'NAME'}).css('width', '12em').appendTo(td);
			td.appendText('◆');
			let sel = $('<select>',{'name': 'SHIFT'}).css('width', '3em');
			for (let i = 0; i < 4; i++) {
				$('<option>').text(i).appendTo(sel);
			}
			sel.change(function() {
				let shifts = $('div', $(this).parent());
				shifts.hide();
				for (let i = 0; i < $(this).prop('selectedIndex')+1; i++) {
					$(shifts[3-i]).show();
				}
			});
			sel.appendTo(td);
			$('<br>').appendTo(td);
			
			for (let i = 0; i < 4; i++) {
				let div = $('<div>').css('white-space', 'nowrap');
				if (i < 3)
					div.css('display', 'none');
				div.appendText('Lv');
				$('<input>', {'type': 'number', 'name': 'LV', 'min': 0}).css('width', '3em').appendTo(div);
				div.appendText('(');
				this.tempClsSelect.clone(true).appendTo(div);
				$('<span>').text(')'+' '.repeat(i)+'◆'.repeat(3-i)+'HP').appendTo(div);
				$('<input>', {'type': 'number', 'name': 'HP', 'min': 0}).css('width', '6em').appendTo(div);
				div.appendTo(td);
			}
			return td;
		},
		// サポートNPC欄の作成
		makeSupport: function() {
			let tbody = $('<tbody>').addClass('support');
			let td = $('<td>', {'colspan': 4, 'class': 'subrow'}).text('サポートNPC(計');
			this.tempClearBtn.clone(true).attr('data-target', 'tbody').prependTo(td);
			let sel = $('<select>', {'name': 'SUPNUM'}).css('width', '3em')
			.append($.map(Array.from({'length': this.settings.max_support+1}, (v, k) => k), function(e) { return $('<option>').text(e); }))
			.prop('selectedIndex', 0)
			.change(function() {
				let lines = $(this).parents('tr').next().find('div');
				var num = $(this).val();
				lines.each(function(i, e) {
					if (num-- > 0)
						$(e).show();
					else
						$(e).hide();
				});
			})
			.appendTo(td);
			td.appendText(')【0=サポ欄非表示】');
			
			tbody.append($('<tr>').append(td));

			td = $('<td>', {'colspan': 4});
			let sunit = this.makeSupportUnit();
			for (let i = 0; i < this.settings.max_support; i++) {
				td.append(sunit.clone(true));
			}
			tbody.append($('<tr>').append(td));
			
			return tbody;
		},
		// サポートNPCの1体の行を生成
		makeSupportUnit: function() {
			let div = $('<div>').css('white-space', 'nowrap').hide();
			div.appendText('隠').append($('<input>', {'type': 'checkbox', 'name': 'HIDE'}));
			$('<input>', {'type': 'text', 'name': 'NAME'}).css('width', '12em').appendTo(div);
			div.appendText(' Lv.');
			$('<input>', {'type': 'number', 'name': 'LV', 'min': 0}).css('width', '3em').appendTo(div);
			div.appendText('(');
			this.tempClsSelect.clone(true).appendTo(div);
			div.appendText(')宝具Lv.');
			$('<input>', {'type': 'number', 'name': 'NOBLELV', 'min': 0, 'max': 5}).css('width', '3em').appendTo(div);
			div.appendText(' [');
			$('<input>', {'type': 'number', 'name': 'SKILL1', 'min': 0, 'max': 10}).css('width', '3em').appendTo(div);
			div.appendText('/');
			$('<input>', {'type': 'number', 'name': 'SKILL2', 'min': 0, 'max': 10}).css('width', '3em').appendTo(div);
			div.appendText('/');
			$('<input>', {'type': 'number', 'name': 'SKILL3', 'min': 0, 'max': 10}).css('width', '3em').appendTo(div);
			div.appendText(']');
			return div;
		},
		getUnits: function() {
			var obj = {
				'BOLD': false,
				'HIDE': false,
				'WAVE': 0,
				'INDEX': 0,
				'NAME': '',
				'BREAK': 0,
				'LV': [],
				'SVTCLS': [],
				'HP': [],
				isEmpty : function() {
					return !this.HP || this.HP.length == 0 || !this.HP[0] || !parseInt(this.HP[0]) || !this.NAME;
				}
			};
			var units = [];
			$('.enemydecks > tr:nth-child(n+2)', this.target).each(function() {
				// 非表示WAVEに当たったら終了
				if ($(this).css('display') == 'none')
					return false;
				var unit = [];
				var nullcnt = 0;
				var wave = parseInt($(this).attr('data-wave'));
				$('td.unit', this).each(function() {
					let svt = $.extend(true, {}, obj);
					svt.BOLD = $('input[name="BOLD"]', this).prop('checked') || false;
					svt.HIDE = $('input[name="HIDE"]', this).prop('checked') || false;
					svt.WAVE = wave;
					svt.INDEX = unit.length;
					svt.NAME = $('input[name="NAME"]', this).val().trim();
					svt.BREAK= $('select[name="SHIFT"]', this).prop('selectedIndex');
					var levels = $('input[name="LV"]:visible', this);
					var classes= $('select[name="SVTCLS"]:visible', this);
					var hps = $('input[name="HP"]:visible', this);
					for (let i = 0; i < svt.BREAK+1; i++) {
						svt.LV.push($(levels[i]).val());
						svt.SVTCLS.push($(classes[i]).val());
						svt.HP.push($(hps[i]).val());
					}
					// 一番上のHP欄と名前欄が埋まってなければNULLと見なす
					if (svt.isEmpty())
						nullcnt++;
					unit.push(svt);
				});
				// 1行全て空なら終了
				if (nullcnt >= 3) {
					return false;
				}
				units = units.concat(unit);
			});
			return units;
		},
		isChecked: function(idname, tgt) {
			if (!tgt) tgt = this.target;
			return $('input[name="'+idname+'"]', tgt).prop('checked');
		},
		// 入力欄からテキスト取得(シンプル)
		getInput: function(idname, tgt) {
			if (!tgt) tgt = this.target;
			let text = $('input[name="'+idname+'"]', tgt).val();
			if (text && text.length > 0)
				return text;
			text = $('select[name="'+idname+'"]', tgt).val();
			if (text && text.length > 0)
				return text;
		},
		generate: function(phase) {
			this.phase = phase;
			let self = this;
			let text = "";
			// thead
			text += Format("|BGCOLOR({0}):CENTER:40|BGCOLOR({0}):CENTER:180|BGCOLOR({0}):CENTER:180|BGCOLOR({0}):CENTER:180|c\n", this.getBg());
			text += Format("|>|>|>|BGCOLOR({0}):COLOR(white):{1}|\n", this.getCaption(), this.getInput("QUESTNAME"));
			text += Format("|{0}{3}|>|{1}|推奨Lv.{2}|\n", this.getInput("AP1"), this.getInput("SPOT"), this.getInput("RECLV"), (this.getInput("AP2")) ? "&br()"+this.getInput("AP2") : "");
			text += Format("|~|絆P : {0}|EXP : {1}|QP : {2}|\n", toComma(this.getInput("BONDP")), toComma(this.getInput("EXP")), toComma(this.getInput("QP")));
			text += Format("|~|>|>|報酬 : {0}|\n", this.getInput("REWARD"));
			// waves : クラス構成
			let units = this.getUnits();
			let wavecnt = this.getInput("WAVECOUNT");
			let clstext = "";
			if ($('input[name="MANUALDETAIL"]', this.target).prop('checked'))
			{
				clstext = this.getInput('DECKDETAIL');
			} else {
				let counts = {};
				$.map(units, function(e, i) {
					if (e.isEmpty()) {
						return '';
					} else {
						counts[e.SVTCLS[0]] = (counts[e.SVTCLS[0]]) ? counts[e.SVTCLS[0]] + 1 : 1;
						return e.SVTCLS[0];
					}
				});
				for (let i = 0; i < this.settings.class_list.length; i++) {
					let key = this.settings.class_list[i];
					if (counts[key]) {
						if (clstext.length > 0)
							clstext += " ";
						clstext += key + counts[key];
					}
				}
			}
			clstext = clstext || "Battleなし";
			text += Format("|>|BGCOLOR({0}):{1} 全{2}回|>|BGCOLOR({0}):{3}|\n", this.getBold(), this.getInput("QID"), wavecnt, clstext);
			// waves : ユニット
			let lastwave = 0;
			for (let i = 0; i < units.length; i++) {
				let svt = units[i];
				if (i % 3 == 0) {
					if (svt.WAVE == lastwave) {
						text += "|~|";
					} else {
						text += Format("|{0}/{1}|", svt.WAVE, wavecnt);
					}
					lastwave = svt.WAVE;
				}
				if (!svt.isEmpty()) {
					let nm = svt.NAME;
					if (svt.BOLD)
						nm = "''"+svt.NAME+"''";
					if (svt.HIDE)
						nm = "&openclose2(){" + nm + "}";
				    text += nm;
				    for (let s = 0; s <= svt.BREAK; s++) {
				    	text += Format("&br()Lv{0}({1})", svt.LV[s], svt.SVTCLS[s]);
				    	if (svt.BREAK > 0)
				    		text += Format("&spanclass(break{0}{1})", svt.BREAK, svt.BREAK - s);
				    	text += Format(" HP{0}", toComma(svt.HP[s]));
				    }
			    } else {
			    	// 空欄は灰色に
			    	text += "BGCOLOR(#ccc):";
			    }
			    text += '|';
			    if (i % 3 == 2)
			    	text += '\n';
			}
			// サポートNPC
			{
				if (this.getInput('SUPNUM') !== '0') {
					text += Format("|>|>|>|BGCOLOR({0}):サポートNPC|\n", this.getBold());
					let atfirst = true;
					text += "|>|>|>|";
					$('.support div:visible', this.target).each(function() {
						if (!atfirst) {
							text += "&br()";
						}
						atfirst = false;
						let nm = $('input[name="NAME"]', this).val();
						if ($('input[name="HIDE"]', this).prop('checked'))
							nm = "&openclose2(){"+nm+"}";
						text += Format("{0} Lv.{1}({2})宝具Lv.{3} [{4}/{5}/{6}]",
							nm,
							$('input[name="LV"]', this).val() || '??',
							$('select[name="SVTCLS"]', this).val(),
							$('input[name="NOBLELV"]', this).val() || '-',
							$('input[name="SKILL1"]', this).val() || '-',
							$('input[name="SKILL2"]', this).val() || '-',
							$('input[name="SKILL3"]', this).val() || '-');
					});
					text += "|\n";
				}
			}
			// エネミー
			{
				$('.enemydetail', this.target).each(function() {
					// 左列行数=0なら非表示
					if ($('select[name="LEFTNUM"]', this).prop('selectedIndex') == 0)
						return true;
					// ヘッダ行
					let nm = self.getInput('NAME', this);
					if (self.isChecked('HIDE', this))
						nm = "&openclose2(){"+nm+"}";
					text += Format("|>|>|>|BGCOLOR({0}):エネミー《{1}》|\n", self.getBold(), nm);
					
					let righttexts = $('textarea[name="RIGHTTEXT"]:visible', this);
					let cnt = 0;
					$('input[name="LEFTTEXT"]:visible', this).each(function() {
						for (let i = 0; i < parseInt(self.getInput('RIGHTNUM', $(this).parent())); i++) {
							if (i == 0) {
								text += Format("|>|{0}|", $(this).val());
							} else {
								text += "|>|~|";
							}
							text += Format(">|{0}|\n", $(righttexts[cnt++]).val().split('\n').join('&br()'));
						}
					});
				});
			}
			// 備考
			{
				let etc = $('input[name="ETCON"]', this.target);
				if (etc.prop('checked')) {
					text += Format("|>|>|>|BGCOLOR({0}):備考欄|\n", this.getBold());
					text += Format("|>|>|>|CENTER:{0}|\n", etc.parents('tbody').find('textarea[name="TEXT"]').val().split('\n').join('&br()'));
				}
			}
			return text;
		},
	};
	
	return function(target, options) {
		return new QuestGen(target, options);
	};
})();

$(function(){
	// 入力欄作成
	var gen = QuestGen($('#here'), {'design': 0});
	gen.makeTable();
	
	$('#createBtn').click(function() {
		let text = gen.generate();
		if (!text) {
			text = 'ここにwiki編集用の文字列が表示されます [出力失敗]';
		}
		$('textarea[name="out"]').val(text);
	});
	
	// 入力消去ボタンの誤操作用ロック
	$('.clearbtn').prop('disabled', true);
	$('#clearLock').change(function() {
		$('.clearbtn').prop('disabled', $(this).prop('checked'));
	});
	// テーブル色変更
	$('select[name="design"]').change(function() {
		let val = $(this).val();
		gen.setDesign(val);
	});
});

</script>
}}}}}

#html2{
<div>
<form name="form0" id="form0">
<textarea name="out" cols="150" rows="20" style="height:100px!important;text-align:left!important;">ここにwiki編集用の文字列が表示されます</textarea></br>
<select style="width:8em;" name="design">
	<option value="0" selected>シナリオ</option>
	<option value="1">フリー</option>
	<option value="2">幕間</option>
</select>
<span style="margin-left:20px"><label><input type="checkbox" id="clearLock" checked>[消]ボタンロック</label></span>
</form>
<form name="form1" id="form1">
<input type="button" value="作成" id="createBtn" style="width:4em;">
<div id="here"></div>
</form>

<div class="template" style="display:none;">
	<table class="phase" cellspacing="1" border="0">
		<thead>
			<tr><td colspan="4" class="headrow">クエスト名 : <input type="text" style="width:15em;" name="QUESTNAME" /></td></tr>
			<tr>
				<td rowspan="3" style="width:80px;"><input type="text" style="width:4em;text-align:center;" name="AP1" value="AP"><br><input type="text" style="width:4em;text-align:center;" name="AP2" /></td>
				<td colspan="2">地名<input type="text" style="width:10em;" name="SPOT" /></td>
				<td>推奨Lv.<input type="text" style="width:4em;" name="RECLV" /></td>
			</tr>
			<tr>
				<td style="width:300px;">絆P : <input type="number" min="0" style="5em;" name="BONDP" /></td>
				<td style="width:300px;">EXP : <input type="number" min="0" style="5em;" name="EXP" /></td>
				<td style="width:300px;">QP : <input type="number" min="0" style="5em;" name="QP" /></td>
			</tr>
			<tr><td colspan="3">報酬 : <input type="text" style="width:15em;" name="REWARD" /></td></tr>
		</thead>
	</table>
</div>
</div>
}