jQuery

コールバック関数・some

map.delete(キー) array.splice(index, 個数(なしの場合はindex以降すべて)) 削除

fabric class継承

fabric (ダブルクリック グループ化)

obj.clickedはundefind → elseを通ってtrue(0.5秒後にfalseになる) → 0.5秒以内に再度クリックするとコールバック関数が実行される。

コールバックではungroupされたあとにisTextGroup()で解除された個々のオブジェクトにitextがあればtrue
→クリックしたオブジェクトがアクティブ(フォーカス当て、編集モード)になる
非アクティブになったら再度グループ化(itextにediting:exitedイベントでグループ化する処理を別で記載)。

jsonをオブジェクトで持たせてmap構造に変換する

画像アップロード

画像アップロード(ajax)

clone(true) 要素のクローンを作成し、選択状態
find(子要素) 子要素を取得

リクエスト(ajax)

当たり判定

モーダル

css

	/*モーダル本体の指定 + モーダル外側の背景の指定*/
	.modal-view {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		text-align: center;
		background: rgba(0, 0, 0, 50%);
		padding: 40px 20px;
		overflow: auto;
		opacity: 0;
		visibility: hidden;
		box-sizing: border-box;
		z-index: 999;
		opacity: 0;
	}

	/*モーダル本体に「active」クラス付与した時のスタイル*/
	.modal-view-conf.active {
		visibility: visible;
		opacity: 1;
		transition: .3s;
	}

	.modal-body-wrap {
		position: relative;
	}

	/*モーダル枠の指定*/
	.modal-body {
		position: absolute;
		display: block;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		margin: auto;
		max-width: 900px;
		width: 70%;
		height: 300px;
	}

	/*モーダルを閉じるボタンの指定*/
	.modal-close {
		position: absolute;
		display: flex;
		align-items: center;
		justify-content: center;
		top: -40px;
		right: -40px;
		width: 40px;
		height: 40px;
		font-size: 40px;
		color: #fff;
		cursor: pointer;
	}

	/*モーダル内のコンテンツの指定*/
	.modal-content {
		background: #fff;
		text-align: left;
		padding: 30px;
	}

	.headline_table {
		border-collapse: separate;
		border-top: 1px solid #DDD;
		border-left: 1px solid #DDD;
	}

	.headline_table td {
		border-right: 1px solid #DDD;
		border-bottom: 1px solid #DDD;
		height: 20px;
		padding-top: 0px;
		padding-bottom: 0px;
	}

html

<div class="modal-view-conf">
					<div class="modal-body">
						<!-- 閉じるボタン -->
						<div class="modal-close">×</div>
						<!-- モーダル内のコンテンツ -->
						<div class="modal-content">
							<table class="headline_table" style="width:100%; margin: 1% 0; border-collapse:collapse; white-space:nowrap;">
								<tr>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
								</tr>
								<tr>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
								</tr>
								<tr>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
								</tr>
								<tr>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
								</tr>
								<tr>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
									<td class=""></td>
								</tr>
							</table>
						</div>
					</div>
				</div>

javascript

//開くボタンをクリックしたらモーダルを表示する
		$('.view-conf').on('click', function(e) {
			e.preventDefault();
			$('.modal-view-conf').addClass('active');
			return false;
		});

		//閉じるボタンをクリックしたらモーダルを閉じる
		$('.modal-close').on('click', function() {
			$('.modal-view-conf').removeClass('active');
		});

		$('.cancel').on('click', function() {
			$('.modal-view-conf').removeClass('active');
		});

		//モーダルの外側をクリックしたらモーダルを閉じる
		$('.modal-view-conf').on('click', function(e) {
			if (!$(e.target).closest('.modal-content').length) {
				$('.modal-view-conf').removeClass('active');
			}
			console.log('クリック', $(e.target).closest('.modal-content'));
		});

$(e.target).closest(‘.modal-content’)

$(document).on('click',   function(e) {
if (!$(e.target).closest('特定の要素のクラス').length) {
// フェードやスライドなどの処理方法を記述;
}
});

まずe.targetでイベントが発生した要素を取得します。
「closest」でその最も近い親要素を指定し、そこに特定の要素があるかを「length」で確認しています。ない場合はlength 0

つまり、クリックした要素の上に特定の要素(親要素)がない場合、
フェードやスライドなどの処理方法を実行という方法になります。

ajax基本

	function updateContent(data, id) {
		const URL = '/admin/admission/result_card/get_preview_html';
		$.ajax({
			url: URL,
			type: 'POST',
			dataType: 'json',
			data: {
				'report_id': id,
				'csrf_token_name': $('input[name="csrf_token_name"]').val(),
			}
		}).done(function(result) {
			if (result.error_message) {
				window.alert(result.error_message);
				return;
			}
			data.content = result.preview_html
			return;
		}).fail(function(jqXHR, textStatus, errorThrown) {
			// console.log(jqXHR, textStatus, errorThrown);
		});
	}

要素を追加

function addItem(element) {
	let clone = $(element).parent().find('div.tmp_select').clone();
	let html = $(clone).html();
	html = '<div class="add_select">' + html +'</div>'
	if($(element).parent().find('div.add_select').length == 0) {
		$(element).parent().find('div.tmp_select').after(html);
	} else {
		$(element).parent().find('div.add_select:last').after(html);
	}
}

function addItem2(element) {
	let clone = $(element).parent().find('div.tmp_select').clone();
	let html = $(clone).html();
	html = '<div class="add_select sub">' + html +'</div>'
	$(element).parent().find('div.tmp_select').after(html);
}

Ajax(FORM_DATA or 通常)

function submitForm(element) {
	var target = $(element).closest('form').attr('id');
	var edit =  $(element).closest('.edit');
	var preview = $(element).closest('.edit').prev('.preview');
	var params = ''

	//総合的な探求の時間の内容・評価 jsonに整形
	if(target == 'sogo_content_evaluate'){
		var data = [];
		for (var i = 0; i < 3; i++) {
			var item_array = new Array();
			let item_list = new Object();
			var key = i + 1 ;
			item_list.type = key;
			$('.add_select').find('select[name="show_yoroku_sogo_manual_select'+key+'[]"]').each(function(inx,elm){
				var item = $(elm).val();
				item_array.push(item);
			})
			$('select[name="show_yoroku_sogo_manual_select'+key+'[]"]').each(function(inx,elm){
				$(elm).prop('disabled',true);
			})

			item_list.items = item_array;

			if(item_list.items.length == 0){
			}else{
				data.push(item_list);
			}
		}
		var json = JSON.stringify(data)
		$('input[name="show_yoroku_sogo_manual_select"]').val(json);
	}

	let useFormData = false;
	let contentType = false;
	if(target == 'tokubetu_record') {
		params = formData(target, edit);
	} else if(target == 'doutoku_record'){
		params = formData(target);
	} else if(target == 'shoken_record') {
		params = formData(target, edit);
	} else if(target == 'attendence_record') {
		params = formData(target);
	} else if(target == 'subject_bikou_record') {
		params = formData(target, edit);
	} else {
		useFormData = true ;
		contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
		params = $('form#'+target).serialize();
	}

	if(!params) {
		return;
	}

	$.ajax({
		url: '/admin/report/conf/yoroku_conf_edit',
		type: 'POST',
		dataType: 'json',
		data: params,
		contentType: contentType ,
		processData: useFormData ,
	}).done(function (result) {
		// エラーメッセージがなければ
		if ($(result.error).length == 0) {
			//更新箇所とメッセージを保存
			localStorage.clear();
			localStorage.setItem("target",target);
			localStorage.setItem("message",result.message);
			//load function発火
			window.location.reload();
		} else {
			//エラーメッセージを表示
			localStorage.clear();
			$(edit).find('.msg').empty();
			$(preview).find('.msg').empty();
			$(result.error).each(function (index, error_message) {
				$(edit).find('.msg').append('<p>' + error_message + '</p>');
			})

			if(target == 'sogo_content_evaluate'){
				for (var i = 1; i <= 3; i++) {
						$('select[name="show_yoroku_sogo_manual_select'+i+'[]"]').each(function(inx,elm){
						$(elm).prop('disabled',false);
					})
				}
			}

		}
	}).fail(function (jqXHR, textStatus, errorThrown) {
		console.log(jqXHR, textStatus, errorThrown);
	});
}

function validsSameValue(array) {
	let set = new Set(array);
	console.log(set.size, array.length);
	return set.size !== array.length;
}


function formData(target, edit = null) {
	const FORM_DATA_MAP = new Map();
	const FORM_DATA = new FormData();
	const SELECT_ITEM_MAP = new Map();
	const SELECT_ARRAY = new Array();
	FORM_DATA.append('use_form_data', target);
	if(target == 'tokubetu_record') {
		FORM_DATA_MAP.set('show_yoroku_tokubetu_manual_type', $('#' + target).find('input:radio[name="show_yoroku_tokubetu_manual_type"]:checked').val());
		FORM_DATA_MAP.set('show_yoroku_tokubetu_manual_text', $('#' + target).find('textarea[name="show_yoroku_tokubetu_manual_text"]').val());
		let result_array = new Array();
		$('#' + target).find('.add_select select[name="show_yoroku_tokubetu_manual_select"] option:selected').each(function(index, data){
			result_array.push($(data).val());
		});
		let isExisted = validsSameValue(result_array);
		if(!isExisted) {
			$('#' + target).find('.add_select select[name="show_yoroku_tokubetu_manual_select"] option:selected').each(function(index, data){
				SELECT_ARRAY.push($(data).val());
			});
		} else {
			$(edit).find('.msg p').remove();
			$(edit).find('.msg').append('<p>同じ項目が複数選択されています。</p>');
			return false;
		}
		SELECT_ITEM_MAP.set('items', SELECT_ARRAY)
		FORM_DATA_MAP.set('show_yoroku_tokubetu_manual_select', JSON.stringify(Object.fromEntries(SELECT_ITEM_MAP)));
		FORM_DATA_MAP.set('show_yoroku_tokubetu_manual_empty', Number($('#' + target).find('input[name="show_yoroku_tokubetu_manual_empty"]').prop('checked')));
		FORM_DATA.append('yoroku_tokubetu_manual', JSON.stringify(Object.fromEntries(FORM_DATA_MAP)));
	} else if(target == 'doutoku_record') {
		FORM_DATA_MAP.set('show_yoroku_doutoku_manual_type', $('#' + target).find('input:radio[name="show_yoroku_doutoku_manual_type"]:checked').val());
		FORM_DATA_MAP.set('show_yoroku_doutoku_manual_text', $('#' + target).find('textarea[name="show_yoroku_doutoku_manual_text"]').val());
		FORM_DATA.append('yoroku_doutoku_manual', JSON.stringify(Object.fromEntries(FORM_DATA_MAP)));
	} else if(target == 'shoken_record') {
		FORM_DATA_MAP.set('show_yoroku_shoken_manual_type', $('#' + target).find('input:radio[name="show_yoroku_shoken_manual_type"]:checked').val());
		FORM_DATA_MAP.set('show_yoroku_shoken_manual_text', $('#' + target).find('textarea[name="show_yoroku_shoken_manual_text"]').val());
		let result_array = new Array();
		$('#' + target).find('.add_select select[name="show_yoroku_shoken_manual_select"] option:selected').each(function(index, data){
			result_array.push($(data).val());
		});
		let isExisted = validsSameValue(result_array);
		if(!isExisted) {
			$('#' + target).find('.add_select select[name="show_yoroku_shoken_manual_select"] option:selected').each(function(index, data){
				SELECT_ARRAY.push($(data).val());
			});
		} else {
			$(edit).find('.msg p').remove();
			$(edit).find('.msg').append('<p>同じ項目が複数選択されています。</p>');
			return false;
		}
		SELECT_ITEM_MAP.set('items', SELECT_ARRAY)
		FORM_DATA_MAP.set('show_yoroku_shoken_manual_select', JSON.stringify(Object.fromEntries(SELECT_ITEM_MAP)));
		FORM_DATA_MAP.set('show_yoroku_shoken_manual_empty', Number($('#' + target).find('input[name="show_yoroku_shoken_manual_empty"]').prop('checked')));
		FORM_DATA.append('yoroku_shoken_manual', JSON.stringify(Object.fromEntries(FORM_DATA_MAP)));
	} else if(target == 'attendence_record') {
		FORM_DATA_MAP.set('show_yoroku_presence_bikou_hosoku', $('#' + target).find('input:radio[name="show_yoroku_presence_bikou_hosoku"]:checked').val());
        // FORM_DATA_MAP.set(); 備考欄に補足集計の文言(追加予定)
        FORM_DATA_MAP.set('show_yoroku_presence_under_text', $('#' + target).find('textarea[name="show_yoroku_presence_under_text"]').val());
        const OBJ = new Object();
        $('#' + target).find('input.show_yoroku_presence_items').each(function(index, data){
            OBJ[$(data).attr('id')] = Number($(data).prop('checked'));
        });
        FORM_DATA_MAP.set('show_yoroku_presence_items', JSON.stringify(OBJ));
        FORM_DATA.append('attendence_record_manual', JSON.stringify(Object.fromEntries(FORM_DATA_MAP)));
	} else if(target == 'subject_bikou_record') {
		FORM_DATA_MAP.set('show_yoroku_subject_bikou_use', $('#' + target).find('input:radio[name="show_yoroku_subject_bikou_use"]:checked').val());
		let result_id_array = new Array();
		$('#' + target).find('.add_select').each(function(index, data){
			result_id_array.push(Number($(data).find('select option:selected').val()));
		});
		let isExistedId = validsSameValue(result_id_array);
		let isExistedText = false;
		let result_text_array = new Array();
		$('#' + target).find('.add_select').each(function(index, data){
			console.log($(data).find('input').val() == '', $(data).find('input').val())
			if($(data).find('input').val() == '') {
				return isExistedText = true;
			}
			result_text_array.push($(data).find('input').val());
		});
		let isExistedSameText = validsSameValue(result_text_array);
		if(!isExistedId && !isExistedSameText && !isExistedText) {
			const OBJECT = new Object();
			$('#' + target).find('.add_select').each(function(index, data){
				const OBJ = new Object();
        	    OBJ['sub_subject_id'] = Number($(data).find('select option:selected').val());
        	    OBJ['text'] = $(data).find('input').val();
				OBJECT[OBJ['sub_subject_id']] = OBJ;
        	});
        	FORM_DATA_MAP.set('show_yoroku_subject_bikou', JSON.stringify(OBJECT));
		} else {
			$(edit).find('.msg p').remove();
			if(isExistedId) {
				$(edit).find('.msg').append('<p>同じ科目が複数選択されています。</p>');
			}
			if(isExistedSameText) {
				$(edit).find('.msg').append('<p>同じテキストが入力されています。</p>');
			}
			console.log("isExistedText", isExistedText)
			if(isExistedText) {
				$(edit).find('.msg').append('<p>未入力のフォームがあります。</p>');
			}
			if(isExistedId || isExistedSameText || isExistedText) {
				return false;
			}
		}
        FORM_DATA.append('subject_bikou_manual', JSON.stringify(Object.fromEntries(FORM_DATA_MAP)));
	}

	return FORM_DATA;
}

FORM_DATAを使う場合のオプションは

  • contentType: false,
  • processData: false ,

通常は

  • contentType: ‘application/x-www-form-urlencoded; charset=UTF-8’;
  • processData: true ,

Javascript(バニラ)

<script>
	(function(){
		/**
		 * 総合的な学習の時間の記録
		 * new_yoroku_flgが2の場合のcss調整
		 * */
		const GAKUNEN = new Object();
		document.querySelectorAll('.sogo_time_record').forEach( (element, index) => {
			let text = element.textContent.trim();
			GAKUNEN[text] = text;
		});
		let ajust_style_100 = new Object();
		let ajust_style_130 = new Object();
		document.querySelectorAll('.sogo_table td').forEach( (element, index) => {
			ajust_style_100[index] = false;
			ajust_style_130[index] = false;
			let gakunen = false
			if(index == 0 || index == 1 || index == 2) {
				typeof GAKUNEN[1] !== 'undefined' && GAKUNEN[1] == 1 ? gakunen = true : gakunen = false;
			} else if(index == 3 || index == 4 || index == 5) {
				typeof GAKUNEN[2] !== 'undefined' && GAKUNEN[2] == 2 ? gakunen = true : gakunen = false;
			} else if(index == 6 || index == 7 || index == 8) {
				typeof GAKUNEN[3] !== 'undefined' && GAKUNEN[3] == 3 ? gakunen = true : gakunen = false;
			}
			let text = element.textContent.trim();
			if(index == 2 || index == 5 || index == 8) {
				if(gakunen && text.length > 100) {
					ajust_style_100[index] = true;
					if(text.length > 130) {
						ajust_style_130[index] = true;
					}
				}
			}
		});
		document.querySelectorAll('.sogo_table td').forEach( (element, index) => {
			if(ajust_style_100[index]) {
				element.style.lineHeight = '13px';
				if(ajust_style_130[index]) {
					element.style.fontSize = '11px';
					element.style.lineHeight = '13px';
				}
			}
		});
	})();
</script>

オブジェクトの中身チェック

typeof GAKUNEN[1] !== ‘undefined’

タイトルとURLをコピーしました