Last active
February 1, 2023 09:21
-
-
Save motsu0/810edcdf680bba0d5f0ca40549451b2e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#message{ | |
color: #e00000; | |
} | |
/* */ | |
.app__menu{ | |
display: flex; | |
column-gap: 8px; | |
} | |
.app__menu__item{ | |
flex-grow: 1; | |
background-color: #ddd; | |
text-align: center; | |
cursor: pointer; | |
} | |
.app__menu__item.on{ | |
background-color: #2ECC71; | |
color: #fff; | |
} | |
.app__body{ | |
/* padding: 12px; */ | |
border: 2px solid #2ECC71; | |
} | |
/* */ | |
.app__block{ | |
padding: 12px; | |
} | |
.copipe{ | |
padding: 8px; | |
border-radius: 4px; | |
background-color: #fff; | |
filter: drop-shadow(0px 0px 2px #777); | |
} | |
.copipe:nth-child(n+2){ | |
margin-top: 20px; | |
} | |
.copipe__area-bt{ | |
margin: 8px 0; | |
} | |
.copipe__head{ | |
display: flex; | |
column-gap: 8px; | |
} | |
.copipe__name{ | |
flex-grow: 1; | |
} | |
.bt-arrow{ | |
width: 20px; | |
cursor: pointer; | |
} | |
.copipe__area-bt{ | |
display: flex; | |
column-gap: 16px; | |
} | |
.bt-copy{ | |
flex-grow: 1; | |
padding: 8px 0; | |
border: none; | |
background-color: #3498DB; | |
color: #fff; | |
} | |
.bt-copy:hover{ | |
background-color: #2980B9; | |
} | |
.bt-copy__icon{ | |
width: 20px; | |
margin-right: 4px; | |
vertical-align: middle; | |
} | |
.bt-del{ | |
border: none; | |
background-color: #fff; | |
color: #E74C3C; | |
} | |
.bt-del:hover{ | |
text-decoration: underline; | |
font-weight: bold; | |
} | |
.bt-control,.copipe__summary{ | |
cursor: pointer; | |
} | |
.copipe__text{ | |
box-sizing: border-box; | |
width: 100%; | |
height: 100px; | |
padding: 4px; | |
resize: vertical; | |
background-color: #eee; | |
font-size: .75rem; | |
} | |
/* */ | |
#input-name-new,#textarea-new{ | |
box-sizing: border-box; | |
display: block; | |
width: 100%; | |
} | |
#textarea-new{ | |
margin: 16px 0; | |
height: 200px; | |
resize: vertical; | |
} | |
#bt-add{ | |
padding: 4px 12px; | |
cursor: pointer; | |
} | |
/* */ | |
.area-del-db{ | |
margin-top: 8px; | |
text-align: right; | |
} | |
#bt-del-db{ | |
border: none; | |
background-color: #fff; | |
font-size: .8rem; | |
color: #555; | |
cursor: pointer; | |
} | |
#bt-del-db:hover{ | |
text-decoration: underline; | |
color: #000; | |
} | |
/* */ | |
.s-hide{ | |
display: none; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="stylesheet" href="pathto/now-loading.css"> | |
<div id="message"></div> | |
<div id="app" class="s-hide"> | |
<div class="app__menu"> | |
<div class="app__menu__item on">保管庫</div> | |
<div class="app__menu__item">新規追加</div> | |
</div> | |
<div class="app__body"> | |
<div id="block-storage" class="app__block"></div> | |
<div class="app__block s-hide"> | |
<input type="text" id="input-name-new" placeholder="定型文の名前"> | |
<textarea id="textarea-new" placeholder="保存したい定型文を入力"></textarea> | |
<button id="bt-add" class="bt-control">新規追加</button> | |
</div> | |
</div> | |
<div class="area-del-db"> | |
<button id="bt-del-db">データベースを削除</button> | |
</div> | |
</div> | |
<!-- テンプレ --> | |
<div id="copipe-origin" class="s-hide"> | |
<div class="copipe__head"> | |
<input type="text" class="copipe__name" placeholder="定型文の名前"></input> | |
<img src="/img/icon/arrow-up-01.svg" alt="上向きの矢印" class="bt-arrow bt-up"> | |
<img src="/img/icon/arrow-down-01.svg" alt="下向きの矢印" class="bt-arrow bt-down"> | |
</div> | |
<div class="copipe__area-bt"> | |
<button class="bt-copy bt-control"> | |
<img src="pathto/copy-white.svg" alt="書類が2枚重なっているアイコン。" class="bt-copy__icon"> | |
<span class="bt-copy__text">コピー</span> | |
</button> | |
<button class="bt-del bt-control">削除</button> | |
</div> | |
<details class="copipe__details"> | |
<summary class="copipe__summary">内容</summary> | |
<textarea class="copipe__text" placeholder="保存したい定型文を入力"></textarea> | |
</details> | |
</div> | |
<script src="pathto/now-loading.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const nowloading = new nowLoading(); | |
// | |
const el_message = document.getElementById('message'); | |
// | |
const el_app = document.getElementById('app'); | |
const els_app__menu__item = document.getElementsByClassName('app__menu__item'); | |
const els_app__block = document.getElementsByClassName('app__block'); | |
// | |
const el_block_storage = document.getElementById('block-storage'); | |
const el_copipe_origin = document.getElementById('copipe-origin'); | |
const els_copipe = document.getElementsByClassName('copipe'); | |
const els_copipe__name = document.getElementsByClassName('copipe__name'); | |
const els_copipe__text = document.getElementsByClassName('copipe__text'); | |
// | |
const el_input_name_new = document.getElementById('input-name-new'); | |
const el_textarea_new = document.getElementById('textarea-new'); | |
const bt_add = document.getElementById('bt-add'); | |
// | |
const bt_del_db = document.getElementById('bt-del-db'); | |
// | |
const name_db = 'copipeDB'; | |
const name_store = 'copipe-storage' | |
let db; | |
// | |
storageInit(); | |
function storageInit(){ | |
nowloading.start(); | |
if(window.indexedDB===undefined){ | |
console.error('indexDB 使用不可'); | |
msgBox('ご利用中の環境ではこのアプリを使用できません。'); | |
nowloading.stop(); | |
return; | |
} | |
bt_add.addEventListener('click',()=>{ | |
addCopipe(el_input_name_new.value,el_textarea_new.value); | |
}); | |
[...els_app__menu__item].forEach((element,i)=>{ | |
element.addEventListener('click',()=>{changeTab(i)}); | |
}); | |
bt_del_db.addEventListener('click',delDB); | |
window.addEventListener('beforeunload',saveData); | |
openDB(); | |
} | |
function openDB(){ | |
//リクエスト発行 データベースを開く | |
const req_open = indexedDB.open(name_db); | |
//成功時 | |
req_open.onsuccess = (event)=>{ | |
console.log('DB接続成功'); | |
//DB取得 | |
db = event.target.result; | |
//トランザクションの開始 | |
const transaction = db.transaction(name_store, 'readonly'); | |
//オブジェクトストア取得 | |
const store = transaction.objectStore(name_store); | |
//リクエスト発行 | |
const req_get = store.get('0'); | |
req_get.onsuccess = (event)=>{ | |
if(req_get.result===undefined){ | |
loadSample(); | |
}else{ | |
loadData(req_get.result); | |
} | |
el_app.classList.remove('s-hide'); | |
nowloading.stop(); | |
}; | |
req_get.onerror = (event)=>{ | |
console.error('DB読込失敗'); | |
msgBox('データの取得に失敗しました。'); | |
nowloading.stop(); | |
} | |
}; | |
//失敗時 | |
req_open.onerror = (error)=>{ | |
console.error('DB接続失敗'); | |
console.error(error); | |
msgBox('データベースへの接続に失敗しました。'); | |
nowloading.stop(); | |
}; | |
//データベース更新時 or 新規作成時 | |
req_open.onupgradeneeded = (event)=>{ | |
console.log('DB新規作成・更新'); | |
const db = event.target.result; | |
const object_store = db.createObjectStore(name_store,{keyPath: 'id'}); | |
}; | |
} | |
function saveData(){ | |
//保存データ作成 | |
const array_data = []; | |
for(let i=0;i<els_copipe__name.length-1;i++){ | |
array_data.push({ | |
name: els_copipe__name[i].value, | |
text: els_copipe__text[i].value | |
}); | |
} | |
const obj_data = { | |
id: '0', | |
data: array_data | |
}; | |
//トランザクションの開始 | |
const transaction = db.transaction(name_store, 'readwrite'); | |
transaction.oncomplete = (event)=>{ | |
console.log('トランザクション完了'); | |
}; | |
transaction.onerror = (event)=>{ | |
console.error('トランザクション失敗'); | |
}; | |
//オブジェクトストア取得 | |
const store = transaction.objectStore(name_store); | |
//リクエスト発行 | |
const req_put = store.put(obj_data); | |
req_put.onsuccess = (event)=>{ | |
console.log('データ書込完了') | |
}; | |
req_put.onerror = (event)=>{ | |
console.error('データ書込失敗'); | |
} | |
} | |
function loadData(result){ | |
if( | |
(result===null) | |
||typeof result !== 'object' | |
||result.data === undefined | |
||!Array.isArray(result.data) | |
){ | |
console.error('DB内データ破損'); | |
msgBox('保存データが破損していたため破棄しました。'); | |
return; | |
} | |
result.data.forEach(val=>{ | |
addCopipe(val.name,val.text); | |
}); | |
} | |
function loadSample(){ | |
const name_sample = 'サンプル定型文'; | |
const text_sample = '定型文のサンプル。\n複数行記述可能。\n上部のコピーボタンから簡単にコピー可能。\n保存後の編集も可能。\n削除や並び替えも可能。'; | |
addCopipe(name_sample, text_sample); | |
} | |
function addCopipe(name,text){ | |
if(text==='') return; | |
nowloading.start(); | |
//クローン作成 | |
const el_copipe = el_copipe_origin.cloneNode(true); | |
el_copipe.id = ''; | |
el_copipe.classList.add('copipe'); | |
el_copipe.classList.remove('s-hide'); | |
//クローン内設定 | |
const el_copipe__name = el_copipe.getElementsByClassName('copipe__name')[0]; | |
el_copipe__name.value = name; | |
const bt_up = el_copipe.getElementsByClassName('bt-up')[0]; | |
bt_up.addEventListener('click',()=>{sortCopipe(el_copipe, 'up')}); | |
const bt_down = el_copipe.getElementsByClassName('bt-down')[0]; | |
bt_down.addEventListener('click',()=>{sortCopipe(el_copipe, 'down')}); | |
const el_copipe__text = el_copipe.getElementsByClassName('copipe__text')[0]; | |
el_copipe__text.value = text; | |
const bt_copy = el_copipe.getElementsByClassName('bt-copy')[0]; | |
const bt_copy__text = el_copipe.getElementsByClassName('bt-copy__text')[0]; | |
bt_copy.addEventListener('click',()=>{copyData(bt_copy, bt_copy__text, el_copipe__text.value);}); | |
const bt_del = el_copipe.getElementsByClassName('bt-del')[0]; | |
bt_del.addEventListener('click',()=>{delCopipe(el_copipe, el_copipe__name.value)}); | |
// | |
el_block_storage.appendChild(el_copipe); | |
el_input_name_new.value = ''; | |
el_textarea_new.value = ''; | |
nowloading.stop(); | |
} | |
function sortCopipe(element, type){ | |
if(type==='up'){ | |
const index_old = [...els_copipe].indexOf(element); | |
if(index_old===0) return; | |
el_block_storage.insertBefore(element, els_copipe[index_old-1]); | |
}else if(type==='down'){ | |
const index_old = [...els_copipe].indexOf(element); | |
if(index_old===els_copipe.length-1) return; | |
el_block_storage.insertBefore(element, els_copipe[index_old+2]); | |
} | |
} | |
function delCopipe(element, name){ | |
const name_short = (()=>{ | |
if(name.length<=10){ | |
return name; | |
}else{ | |
return name.slice(0,10)+'…'; | |
} | |
})(); | |
if(window.confirm(`「${name_short}」を削除しますか?`)){ | |
element.remove(); | |
} | |
} | |
function delDB(){ | |
if(window.confirm('全てのデータを削除しますか?')){ | |
db.close(); | |
const req_del = indexedDB.deleteDatabase(name_db); | |
req_del.onsuccess = (event)=>{ | |
console.log('DB削除成功'); | |
el_app.textContent = ''; | |
msgBox('データベース削除完了。<br>再び使用したい場合はページを再読み込みしてください。'); | |
}; | |
req_del.onerror = (event)=>{ | |
console.error('DB削除失敗'); | |
}; | |
} | |
} | |
function changeTab(index_clicked){ | |
for(let i=0;i<els_app__menu__item.length;i++){ | |
if(i==index_clicked){ | |
els_app__menu__item[i].classList.add('on'); | |
els_app__block[i].classList.remove('s-hide'); | |
}else{ | |
els_app__menu__item[i].classList.remove('on'); | |
els_app__block[i].classList.add('s-hide'); | |
} | |
} | |
} | |
function msgBox(str){ | |
el_message.innerHTML = str; | |
} | |
function copyData(bt, bt__text, text){ | |
navigator.clipboard.writeText(text).then(()=>{ | |
if(!bt.classList.contains('s-copied')){ | |
bt.classList.add('s-copied'); | |
bt__text.textContent = 'Copied!'; | |
setTimeout(()=>{ | |
bt.classList.remove('s-copied'); | |
bt__text.textContent = 'コピー'; | |
},2000); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment