47日目 割烹芸人の開発7
こーどを……
次はヘッダーを作っていきます。
Editor.jsのプラグインにヘッダーもありますが、h1~h6の切り替えしかないのでカスタマイズします。
また小説家になろうではhタグは拡張性が低いのでdivで実装していきます。
class Header{
constructor({data, config, api}){
this.api=api;
this.config = config || {};
this.data = {
text: data.texxt || '',
position:data.position !== undefined ? data.position : 'left',
level: data.level !== undefined ? data.level : '1.5',
type: data.type !== undefined ? data.type : 'under-line',
color: data.color !== undefined ? data.color : '#000',
backcolor: data.color !== undefined ? data.color : '#fff',
bordercolor: data.color !== undefined ? data.color : '#000'
};
this._setform = false;
this._element = this.drawView();
this._element.style.fontSize=this.data.level + 'em';
this._changePosition(this.data.position);
this._element.classList.toggle(this.data.type);
this.settings = [
{
name:'2',
icon:'特大'
},
{
name:'1.5',
icon:'並大'
},
{
name:'1.2',
icon:'中大'
},
{
name:'left',
icon:'左寄'
},
{
name:'center',
icon:'中央'
},
{
name:'right',
icon:'右寄'
},
{
name:'normal',
icon:'普通'
},
{
name:'left-line',
icon:'左線'
},
{
name:'under-line',
icon:'下線'
},
{
name:'updown-line',
icon:'上下'
},
{
name: 'Border',
icon:'枠線'
},
{
name: 'needlework',
icon:'刺繍'
},
{
name: 'color',
icon:'彩色',
}
]
}
drawView() {
const containr = document.createElement('div');
const textblock = document.createElement('div');
const setblock = document.createElement('form');
containr.classList.add('custom-header');
textblock.contentEditable = true;
containr.appendChild(textblock);
containr.appendChild(setblock);
return containr;
}
render(){
return this._element;
}
save(toolsContent){
return {
text:toolsContent.innerHTML,
level:this.data.level,
type:this.data.type,
position:this.data.position,
color:this.data.color,
bordercolor:this.data.bordercolor,
backcolor:this.data.backcolor
}
}
validate(blockData) {
return blockData.text.trim() !== '';
}
static get toolbox(){
return {
icon:'見出',
title:'見出しを挿入'
};
}
}
こんな感じにまずは全体を作ります。
パラメータとしては
text:
level:
type:
position:
color:
bordercolor:
backcolor:
ですね。
レンダーはテキスト書く部分とフォーム部に分けて指定します。
最初は一つのコンテナに詰め込んでましたが、設定がやりにくかったのでそうしました。
次にレンダーセッティングを作っていきます。
renderSettings(){
const wrapper = document.createElement('div');
this.settings.forEach(tune =>{
let button = document.createElement('div');
button.classList.add(this.api.styles.settingsButton);
button.innerHTML = tune.icon;
wrapper.appendChild(button);
if(tune.name === 'normal' || tune.name === 'left-line' || tune.name === 'under-line' || tune.name === 'updown-line' || tune.name === 'Border' || tune.name === 'needlework'){
button.classList.toggle(this.api.styles.settingsButtonActive, tune.name === this.data.type);
}else if(tune.name === '2' || tune.name === '1.5' || tune.name === '1.2'){
button.classList.toggle(this.api.styles.settingsButtonActive, tune.name === this.data.level);
}else if(tune.name === 'left' || tune.name === 'center' || tune.name === 'right'){
button.classList.toggle(this.api.styles.settingsButtonActive, tune.name === this.data.position);
}else{
if(this._setform){
button.classList.toggle(this.api.styles.settingsButtonActive);
}
}
button.addEventListener('click', ()=>{
if(tune.name === 'normal' || tune.name === 'left-line' || tune.name === 'under-line' || tune.name === 'updown-line' || tune.name === 'Border' || tune.name === 'needlework'){
wrapper.querySelectorAll(`.${this.api.styles.settingsButton}`).forEach(el => {
if((el.innerHTML === '普通' || el.innerHTML === '左線' || el.innerHTML === '下線' || el.innerHTML === '上下' || el.innerHTML === '枠線' || el.innerHTML === '刺繍') ){
el.classList.remove(this.api.styles.settingsButtonActive);
}
});
button.classList.add(this.api.styles.settingsButtonActive);
this._changeType(tune.name);
}else if(tune.name === '2' || tune.name === '1.5' || tune.name === '1.2'){
wrapper.querySelectorAll(`.${this.api.styles.settingsButton}`).forEach(el => {
if((el.innerHTML === '特大' || el.innerHTML === '並大' || el.innerHTML === '中大') ){
el.classList.remove(this.api.styles.settingsButtonActive);
}
});
button.classList.add(this.api.styles.settingsButtonActive);
this._changeSize(tune.name);
}else if(tune.name === 'left' || tune.name === 'center' || tune.name === 'right'){
wrapper.querySelectorAll(`.${this.api.styles.settingsButton}`).forEach(el => {
if((el.innerHTML === '左寄' || el.innerHTML === '中央' || el.innerHTML === '右寄') ){
el.classList.remove(this.api.styles.settingsButtonActive);
}
});
button.classList.add(this.api.styles.settingsButtonActive);
this._changePosition(tune.name);
}else if(tune.name === 'color'){
button.classList.toggle(this.api.styles.settingsButtonActive);
if(button.classList.contains(this.api.styles.settingsButtonActive)){
this._showColorPicker();
this._setform=true;
}else{
this._hideColorPicker();
this._setform=false;
}
}else{
}
});
});
return wrapper;
}
_removeTypeClass(){
const typelist = ['normal','left-line','under-line','updown-line','Border','needlework'];
for(const type of typelist){
this._element.classList.remove(type);
}
}
_changeType(tune){
this._removeTypeClass();
this._element.classList.toggle(tune);
this.data.type=tune;
}
_changeSize(tune){
const headerbox = this._element.querySelector('div');
this.data.level=tune;
headerbox.style.fontSize=tune + 'em';
}
_changePosition(tune){
this.data.position=tune;
this._element.classList.remove('center');
this._element.classList.remove('right');
this._element.classList.remove('left');
this._element.classList.add(tune);
}
_showColorPicker(){
const setbox = this._element.querySelector('form');
const textcolor = document.createElement('input');
const backcolor = document.createElement('input');
const bordercolor = document.createElement('input');
textcolor.type = 'color';
textcolor.value = this.data.color;
backcolor.type = 'color';
backcolor.value = this.data.backcolor;
bordercolor.type = 'color';
bordercolor.value = this.data.bordercolor;
setbox.insertAdjacentHTML('beforeend', '文字色:');
setbox.appendChild(textcolor);
setbox.insertAdjacentHTML('beforeend', '
背景色:');
setbox.appendChild(backcolor);
setbox.insertAdjacentHTML('beforeend', '
枠色:');
setbox.appendChild(bordercolor);
textcolor.onchange = () => {
const headerbox = this._element.querySelector('div');
this.data.color = textcolor.value;
headerbox.style.color=this.data.color;
};
backcolor.onchange = () => {
const headerbox = this._element.querySelector('div');
this.data.backcolor = backcolor.value;
headerbox.style.background=this.data.backcolor;
};
bordercolor.onchange = () => {
const headerbox = this._element.querySelector('div');
this.data.bordercolor = bordercolor.value;
headerbox.style.borderColor=this.data.bordercolor;
};
}
_hideColorPicker(){
const setbox = this._element.querySelector('form');
setbox.innerHTML='';
}
こんな感じですね。分岐しまくってますが、まぁ……動けばいいかな。
こんな感じに色々と選べるようになってます。
彩色ボタンを押すとフォームが出てきます。そこで色を選ぶ感じ。
ドロップボックスでカラーセットみたいにするといいのかも。
まぁいいや。あとコピペには対応させてない。divブロックはセパレーターがあるからちょっとなぁと……。最初からヘッダーにすればよかったんだ……。