20210609のJavaScriptに関する記事は27件です。

【Vue.js】親・子のコンポーネント間でのv-modle

はじめに 仕事で使う事になったので1からVue.jsについて学んだ。 ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。 親・子のコンポーネント間でv-modleを使う(双方向データバインディングする) ソースコードとしては以下。 親・子 SFC名 親 App.vue 子 EventTitle.vue App.vue <template> <div class="container-sm"> <!-- 省略 --> <div> <h2>イベントのフォーム</h2> <EventTitle :value="eventData.title" @input="eventData.title = $event" ></EventTitle> <!-- <EventTitle v-model="eventData.title"></EventTitle> ←v-modelは上記のように書き換えられる --> </div> </div> </template> <script> // 省略 import EventTitle from "./components/EventTitle.vue"; export default { data() { return { // 省略 eventData: { title: "", }, }; }, components: { // 省略 EventTitle, }, // 省略 }; </script> EventTitle.vue <template> <div> <p>タイトル</p> <div class="form-floating mb-3"> <input type="text" class="form-control" id="title" placeholder="タイトル" :value="value" @input="$emit('input', $event.target.value)" /> <label for="title">タイトル</label> </div> <p>{{ value }}</p> </div> </template> <script> export default { props: ["value"], }; </script> ソースコード全体は以下。 どのようにしてv-modelが動作する流れを詳細に見ていくと、、、(どこからスタートするかは鶏と卵であるが) 親コンポーネントの:valuev-bind:valueの事であり、value属性を動的にバインド(value属性の値に設定する)するという事をする最初は空文字なので空文字がバインドされる 子コンポーネントのprops: ["value"]親→子のコンポーネント間のデータ渡しの仕組みであるpropsを使い、親コンポーネントの属性名と同じ名前にする事で親コンポーネントの値を受け取る 子コンポーネントの:value="value"propsで受け取った値をinputタグのvalue属性にv-bindでバインドするこれにより親コンポーネントで定義していたeventData.titleが子コンポーネントのinput要素に反映されるようになる 子コンポーネントの@input="$emit('input', $event.target.value)"子→親のコンポーネント間のデータ渡しの仕組みである$emit()を用いて、inputに入力があった際に親コンポーネントのカスタムイベントを発火させる今回は親コンポーネントの@inputを発火させたいので第一引数がinputになっており、$emitで副次的に渡せる値としてはinputに入力された値を渡したいので、第二引数が$event.target.valueになっている※$event.target.valueの$eventはDOMに備わっているイベントオブジェクトで、今回はinput要素への入力で発火したイベントオブジェクトが格納される(子コンポーネントの@input) 親コンポーネントの@input="eventData.title = $event"子コンポーネントから$emit()で発火されたイベントが親コンポーネントで発火し、eventData.titleに$event($emitを使っている場合は$emitの第二引数に渡しているもの)が代入されるこれにより子コンポーネントの入力内容が親コンポーネントのオブジェクトに格納される このような流れで、親・子のコンポーネント間でのv-modelは実現される。 ※ソースコードの注意事項としては、 <EventTitle :value="eventData.title" @input="eventData.title = $event" ></EventTitle> と <EventTitle v-model="eventData.title"></EventTitle> は全く同じもので、v-modelが:value="eventData.title"・@input="eventData.title = $event"というのを書かないでいいようにしてくれているだけ。 実際に内部的に動いているのは:value="eventData.title"・@input="eventData.title = $event"を書いた方なので、上記のような「v-modelが動作する流れ」になる。そのため、props: ["value"]のvalueをtestに書き換えて、v-bindの代入元のvalueもtestにしても動作しない。これは暗黙的に:value="eventData.title"・@input="eventData.title = $event"で処理されているから。 以下は動作する場合と動作しない場合の動画。 Vue.jsの勉強メモ一覧記事へのリンク Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。 https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】親・子のコンポーネント間でのv-model

はじめに 仕事で使う事になったので1からVue.jsについて学んだ。 ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。 親・子のコンポーネント間でv-modelを使う(双方向データバインディングする) ソースコードとしては以下。 親・子 SFC名 親 App.vue 子 EventTitle.vue App.vue <template> <div class="container-sm"> <!-- 省略 --> <div> <h2>イベントのフォーム</h2> <EventTitle :value="eventData.title" @input="eventData.title = $event" ></EventTitle> <!-- <EventTitle v-model="eventData.title"></EventTitle> ←v-modelは上記のように書き換えられる --> </div> </div> </template> <script> // 省略 import EventTitle from "./components/EventTitle.vue"; export default { data() { return { // 省略 eventData: { title: "", }, }; }, components: { // 省略 EventTitle, }, // 省略 }; </script> EventTitle.vue <template> <div> <p>タイトル</p> <div class="form-floating mb-3"> <input type="text" class="form-control" id="title" placeholder="タイトル" :value="value" @input="$emit('input', $event.target.value)" /> <label for="title">タイトル</label> </div> <p>{{ value }}</p> </div> </template> <script> export default { props: ["value"], }; </script> ソースコード全体は以下。 どのようにしてv-modelが動作する流れを詳細に見ていくと、、、(どこからスタートするかは鶏と卵であるが) 親コンポーネントの:valuev-bind:valueの事であり、value属性を動的にバインド(value属性の値に設定する)するという事をする最初は空文字なので空文字がバインドされる 子コンポーネントのprops: ["value"]親→子のコンポーネント間のデータ渡しの仕組みであるpropsを使い、親コンポーネントの属性名と同じ名前にする事で親コンポーネントの値を受け取る 子コンポーネントの:value="value"propsで受け取った値をinputタグのvalue属性にv-bindでバインドするこれにより親コンポーネントで定義していたeventData.titleが子コンポーネントのinput要素に反映されるようになる 子コンポーネントの@input="$emit('input', $event.target.value)"子→親のコンポーネント間のデータ渡しの仕組みである$emit()を用いて、inputに入力があった際に親コンポーネントのカスタムイベントを発火させる今回は親コンポーネントの@inputを発火させたいので第一引数がinputになっており、$emitで副次的に渡せる値としてはinputに入力された値を渡したいので、第二引数が$event.target.valueになっている※$event.target.valueの$eventはDOMに備わっているイベントオブジェクトで、今回はinput要素への入力で発火したイベントオブジェクトが格納される(子コンポーネントの@input) 親コンポーネントの@input="eventData.title = $event"子コンポーネントから$emit()で発火されたイベントが親コンポーネントで発火し、eventData.titleに$event($emitを使っている場合は$emitの第二引数に渡しているもの)が代入されるこれにより子コンポーネントの入力内容が親コンポーネントのオブジェクトに格納される このような流れで、親・子のコンポーネント間でのv-modelは実現される。 ※ソースコードの注意事項としては、 <EventTitle :value="eventData.title" @input="eventData.title = $event" ></EventTitle> と <EventTitle v-model="eventData.title"></EventTitle> は全く同じもので、v-modelが:value="eventData.title"・@input="eventData.title = $event"というのを書かないでいいようにしてくれているだけ。 実際に内部的に動いているのは:value="eventData.title"・@input="eventData.title = $event"を書いた方なので、上記のような「v-modelが動作する流れ」になる。そのため、props: ["value"]のvalueをtestに書き換えて、v-bindの代入元のvalueもtestにしても動作しない。これは暗黙的に:value="eventData.title"・@input="eventData.title = $event"で処理されているから。 以下は動作する場合と動作しない場合の動画。 Vue.jsの勉強メモ一覧記事へのリンク Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。 https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

InDesign スクリプト 要素の内容を配置(指定された要素のテキストフレーム等を複製して構造の選択された属性の値のページに)

指定された要素のテキストフレーム等を複製して構造の選択された属性の値のページに要素の内容を配置するスクリプトは、これで良いのかな・・・? /* 指定された要素のテキストフレーム等を複製して構造の選択された属性の値のページに要素の内容を配置 更新 2021/06/10 */ // アプリ指定 #target "indesign"; // スクリプト名 var scriptName = "要素の内容を配置(指定された要素のテキストフレーム等を複製して構造の選択された属性の値のページに)"; //スクリプト動作指定(一つのアンドゥ履歴にする及びアンドゥ名の指定) app.doScript(function () { // ダイアログ var dialogueFlg = confirm("構造の選択された属性の値のページに最後に選択された属性の要素のテキストフレーム等を複製して要素の内容をページの左上を原点にした位置に配置。" + "\r\r" + "正数の値の入った属性を選択して実行してください。", "", scriptName); // Noの場合 if (dialogueFlg == false) { // スクリプトを終了 exit(); } // 選択されているオブジェクト(配置されるとその要素が自動で選択され属性の選択が外れてしまう為) var selectObjects = app.activeDocument.selection; // 配列の順番を逆にする // (属性は)選択した順番の逆に入っているのを選択した順番にする selectObjects.reverse(); // 選択が0より多い場合 if(selectObjects.length > 0){ // 基準のオブジェクトの位置と大きさ var baselineObjectGeometricBounds; // 基準のオブジェクトのページの位置と大きさ var baselineObjectPageBounds; // 基準のオブジェクトのフラグにfalseを入れる var baselineObjectFlg = false; // 最後の選択が属性の場合 if(selectObjects[selectObjects.length - 1].constructor.name == "XMLAttribute"){ // (最後の選択の属性の親の)要素の参照がStoryの場合 if(selectObjects[selectObjects.length - 1].parent.xmlContent.constructor.name == "Story"){ // 基準のオブジェクトの位置と大きさに(最後の選択の)要素の参照の持つ最初のテキストフレームの位置と大きさを入れる baselineObjectGeometricBounds = selectObjects[selectObjects.length - 1].parent.xmlContent.textContainers[0].geometricBounds; // (最後の選択の属性の親の要素の参照のテキストフレーム等の)parentPageに値がある場合 if (selectObjects[selectObjects.length - 1].parent.xmlContent.textContainers[0].parentPage){ // 元のオブジェクトのページの位置と大きさに最後の選択の要素の親の属性の参照の最初のテキストフレーム等のあるページの位置と大きさを入れる baselineObjectPageBounds = selectObjects[selectObjects.length - 1].parent.xmlContent.textContainers[0].parentPage.bounds; // 選択に親の要素を追加 selectObjects[selectObjects.length - 1].parent.select(SelectionOptions.addTo); // 基準のオブジェクトのフラグにtrueを入れる baselineObjectFlg = true; } // 以外の場合 }else{ // 多角形とか追加 } } // 基準のオブジェクトのフラグがfalseの場合 if(baselineObjectFlg == false){ // 選択状態を元に戻す app.activeDocument.selection = selectObjects; // 結果表示 alert("最後に選択された属性の要素のページ(ページアイテム)を取得出来ませんでした。",scriptName); // スクリプトを終了 exit(); } // 配置ページ番号 var placePageNumber; // 配置数 var placeNumber = 0; // 配置の位置と大きさ var placeBounds; // 選択の数引く1だけ繰り返す for(var i = 0; i < selectObjects.length - 1; i++){ // 選択が属性の場合 if (selectObjects[i].constructor.name == "XMLAttribute"){ // ストーリーのコンストラクタ名を取得する関数を使い結果がXmlストーリーの場合 if(getStoryConstructorName(selectObjects[i]) == "XmlStory"){ // 属性の値が正数の場合 if(selectObjects[i].value.match(/^[1-9][0-9]*$/) != null){ // 配置ページ番号に入れる placePageNumber = selectObjects[i].value; // 配置ページ番号のページが存在する場合 if(app.activeDocument.pages.item(placePageNumber - 1).isValid == true){ // 配置の位置と大きさに位置と大きさを指定する関数の結果を入れる placeBounds = assignBounds(baselineObjectGeometricBounds,baselineObjectPageBounds,app.activeDocument.pages.item(placePageNumber - 1).bounds) // 要素の内容を構造の選択された属性の値のページに最後に選択された属性の要素のテキストフレーム等を複製してページの左上を原点にした位置に配置ページ番号のページに配置 selectObjects[i].parent.placeIntoCopy(app.activeDocument.pages.item(placePageNumber - 1),[placeBounds[0],placeBounds[1]],selectObjects[selectObjects.length - 1].parent.xmlContent.textContainers[0]); // 配置数を追加 placeNumber++; } } } } } // 結果表示 alert("指定の元の要素と指定された要素を選択しました。" + "\r" + "配置予定数(最後の選択を除いた数) " + (selectObjects.length - 1) + "\r" + "配置数 " + placeNumber,scriptName); } //スクリプト動作指定(一つのアンドゥ履歴にする及びアンドゥ名の指定)の続き }, ScriptLanguage.JAVASCRIPT, [scriptName], UndoModes.ENTIRE_SCRIPT, scriptName); /* ストーリーのコンストラクタ名を取得する関数、引数(オブジェクト)の宣言 */ function getStoryConstructorName(anyObject) { // parentStoryプロパティが存在する場合 if (anyObject.hasOwnProperty("parentStory") == true) { // parentStoryがある場合 if (anyObject.parentStory) { // ストーリーのコンストラクタ名を戻す return anyObject.parentStory.constructor.name; } // スプレッドの場合 } else if (anyObject.constructor.name == "Spread") { // 抜ける return; } // オブジェクトの階層を一つ上げて再帰関数 return getStoryConstructorName(anyObject.parent); } /* ストーリーのコンストラクタ名を取得する関数の宣言終了 */ /* 位置と大きさを指定する関数、引数(元のオブジェクトの位置と大きさ、元のオブジェクトのページの位置と大きさ、選択オブジェクトのページの位置と大きさ)の宣言*/ function assignBounds(baselineObjectGeometricBounds,baselineObjectPageBounds,selectObjectPageBounds){ // 指定するオブジェクトの位置と大きさ var assignObjectBounds = [0,0,0,0]; // 指定するオブジェクトの位置と大きさの左上のYに基準のオブジェクトの位置と大きさの左上のY引く基準のオブジェクトのページの位置と大きさの左上のY足す選択オブジェクトのページの位置と大きさの左上のYを入れる assignObjectBounds[0] = baselineObjectGeometricBounds[0] - baselineObjectPageBounds[0] + selectObjectPageBounds[0]; // 指定するオブジェクトの位置と大きさの左上のXに基準のオブジェクトの位置と大きさの左上のX引く基準のオブジェクトのページの位置と大きさの左上のX足す選択オブジェクトのページの位置と大きさの左上のXを入れる assignObjectBounds[1] = baselineObjectGeometricBounds[1] - baselineObjectPageBounds[1] + selectObjectPageBounds[1]; // 指定するオブジェクトの位置と大きさの左上のYに基準のオブジェクトの位置と大きさの左上のY引く基準のオブジェクトのページの位置と大きさの左上のY足す選択オブジェクトのページの位置と大きさの左上のYを入れる assignObjectBounds[2] = baselineObjectGeometricBounds[2] - baselineObjectPageBounds[0] + selectObjectPageBounds[0]; // 指定するオブジェクトの位置と大きさの左上のXに基準のオブジェクトの位置と大きさの左上のX引く基準のオブジェクトのページの位置と大きさの左上のX足す選択オブジェクトのページの位置と大きさの左上のXを入れる assignObjectBounds[3] = baselineObjectGeometricBounds[3] - baselineObjectPageBounds[1] + selectObjectPageBounds[1]; // 指定するオブジェクトの位置と大きさを返す return assignObjectBounds; } /* 位置と大きさを指定する関数の宣言終了*/ たとえば 以下の様なXml(文字コードはUTF-8)をInDesignの構造に読み込み そのうちの一つをレイアウトに配置してテキストフレーム設定等を行ったのち 配置したい要素のページの番号の値の入った属性を選択して (属性の選択を補助するスクリプトあり) 最後に先ほど配置した要素の属性を選択して使用します。 1つの要素を複数配置する事は出来ません。 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Root> <猫の名前 placePage="1">こはく</猫の名前> <猫の名前 placePage="2">ぼんた</猫の名前> <猫の名前 placePage="3">くろい</猫の名前> </Root>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

タブメニュー

タブメニューの実装 HTML data-id属性で紐付ける index.html <section> <ul class="tab-menu"> <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger is-active" data-id="tab01">タブ1</span></li> <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab02">タブ2</span></li> <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab03">タブ3</span></li> </ul> <div class="tab-content"> <div class="tab-content__item js-tab-target is-active" id="tab01"> <p>タブ1の内容</p> </div> <div class="tab-content__item js-tab-target" id="tab02"> <p>タブ2の内容</p> </div> <div class="tab-content__item js-tab-target" id="tab03"> <p>タブ3の内容</p> </div> </div> </section> jQuery 実装手順 ①全部の要素からclassは外し、クリックした要素にのみclass付与する ②操作元のdata属性と操作対象のidを合わせる main.js $(function () { $('.js-tab-trigger').on('click', function () { //全triggerからclass削除 $('.js-tab-trigger').removeClass('is-active'); //全targetからclass削除 $('.js-tab-target').removeClass('is-active'); //クリックした要素にis-active $(this).addClass('is-active'); //data属性を取得する let id = $(this).data("id"); //data属性値=idが等しいものにclass付与 $('#' + id).addClass('is-active') }); }); JavaScript 実装手順 ①トリガーの数だけforEachでループ処理を行い、値を取り出す ②トリガー要素の’.js-tab-trigger’がクリックされたら、クリックされた要素を特定するために変数currentMenuに格納(thisでも代用可能) ③その変数から指定のターゲット要素をdata-id属性から取得して、変数currentContentとして保持 ④タブメニュー全てのアクティブクラスの’.is-active’をトリガーの数だけforEachでループさせて削除、クリックされた要素(currentMenu)にのみ’.is-active’を付加 main.js document.addEventListener('DOMContentLoaded', () => { // タブメニュークラス'.js-tab-trigger'を持つ要素を取得 const tabTriggers = document.querySelectorAll('.js-tab-trigger'); // タブコンテンツクラス'.js-tab-target'を持つ要素を取得 const tabTargets = document.querySelectorAll('.js-tab-target'); // 要素の数の分だけループ処理をして値を取り出す tabTriggers.forEach(tabTrigger => { // タブメニュークリック時 tabTrigger.addEventListener('click', (e) => { // クリックされた要素(メニュー要素[トリガー要素])を取得 let currentMenu = e.currentTarget // ターゲットとなる要素(タブメニューdata属性値と等しいid値を持つコンテンツ要素[ターゲット要素])を取得 let currentContent = document.getElementById(currentMenu.dataset.id) // すべてのタブメニューの'is-active'クラスを削除 tabTriggers.forEach(tabTrigger => { tabTrigger.classList.remove('is-active') }); // クリックしたタブメニューに'is-active'クラスを追加 currentMenu.classList.add('is-active') // タブコンテンツを非アクティブにする tabTargets.forEach(tabTarget => { tabTarget.classList.remove('is-active') }); // 対象コンテンツ(指定したIDの要素があったら)を表示させる if (currentContent !== null) { currentContent.classList.add('is-active') } }) }); });
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js todoリスト 理解用

todoリストで調べた点 todoリストのチュートリアルを通して疑問に感じた点を備忘録とこれから学んでいく人のために記している。 ディレクティブ"v-"で始まる属性である。基本的にJavaScriptの記法と同じだが、"v-for"と"v-on"は例外となる。 v-vind属性を動的にできる。クリック時のリンク切り替えなどができる。todoリストの場合はリスト一覧から一つずつ取ってくるため、for文とともに切り替えていると考えられる。 v-onイベントを発動するトリガーとして使う。ボタンクリック時に関数を呼び出したりする。todoリストではsubmitイベントはformで起こるのでformに挿入する。preventはページがリロードされないようにしている。 pushJavaScriptでの配列の追加方法 watchオブジェクトの追加、削除を監視する役割を持つ。deepをtrueにすることで中身の変更も監視する。 ? :(三項演算子)A = B ? 0 : 1 においてA=Bなら0を返し、A!=Bなら1を返す。todoリストでは三項演算子でフラグを反転している。item.state(現状) = item.state(== 1) ?となっている。item.stateが両辺で別ということを意識してほしい。 splice配列の要素を取り除く方法。index番目の要素から1つ取り除く。 参考 ディレクティブ: https://v3.vuejs.org/guide/template-syntax.html#directives v-bind: https://kinocolog.com/vue_v_bind/ v-on: https://jp.vuejs.org/v2/guide/events.html watch:https://qiita.com/Keitaro/items/8e3f8448d1a0fe281648 フラグの反転: https://qiita.com/day-1/items/737523837e3803f3d3e9
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript 四則演算

四則演算 まとめ //足し算 console.log(4+2); //引き算 console.log(4-2); //掛け算 console.log(4*2); //割り算 console.log(4/2); //余り console.log(4%2); 結果
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsでGitHubのオーガナイゼーションとチームにユーザーを追加する

GitHubのチームはオーガナイゼーションに紐づくサブ組織的な位置付けです。 GitHubのオーガナイゼーションとチーム このような階層構造になっています。 オーガナイゼーション1 |--チームA |--チームB |--チームC オーガナイゼーションのメンバーとして管理権限がないと、オーガナイゼーション外のユーザーをオーガナイゼーション配下のチームに追加することは出来ません。 例えば、チームBにだけメンバーを追加しようとしても、オーガナイゼーション1に先に追加しないといけません。さらにこれをやる場合、オーガナイゼーション1の管理権限がないといけません。 オーガナイゼーション1に所属している管理権限がない人でもチームに人を追加できるように出来ないかと思い、APIを使ってみました。 GitHubのAPIアクセストークンを発行 こちら(個人アクセストークンを使用する)をみてアクセストークンを取得します。 Settings > Developer settings > Personal access tokensで見れます オーガナイゼーションだけのコントロールをしたいのでこんなチェックにしてトークンを発行しました。 ghp_で始まる文字列がトークンとして発行されます。 GitHubのチーム追加のAPIをまずはCURLで試す Add or update team membership for a userを見てみます。 /orgs/{org}/teams/{team_slug}/memberships/{username} という形式でAPIを叩くことで利用できます。 $ curl -u {ORG_NAME}:{トークン} -X PUT -H "Accept: application/vnd.github.inertia-preview+json" https://api.github.com/orgs/{ORG_NAME}/teams/{TEAM_NAME}/memberships/{USER_NAME} -d '{"role":"member"}' こんな形式で利用することができました。 Node.js(axios)からAPIを利用する 先程のCURLのコマンドからaxiosに書き換えてみます。-uオプションはベーシック認証なんですね。 逆引きcurlコマンドのオプション一覧 $ npm i axios app.js const axios = require(`axios`); const gh = async () => { const TOKEN = `トークンを指定`; const ORG = `protoout`; //追加先のオーガナイゼーション const TEAM = `protoout-student`; //追加するチーム名 const USER_NAME = `n0bisuke`; //追加するユーザー const BASE_URL = `https://api.github.com`; const PATH = `/orgs/${ORG}/teams/${TEAM}/memberships/${USER_NAME}` const config = { baseURL: BASE_URL, url: PATH, method: 'put', headers: { 'Content-Type': 'application/json', 'Accept': 'application/vnd.github.inertia-preview+json', }, auth: { username: ORG, password: TOKEN }, data: { 'role': 'member' //固定 API経由で管理者を追加することはあんまりなさそう } }; const res = await axios.request(config); console.log(res.data); } gh(); 実行結果 $ node app.js { state: 'active', role: 'maintainer', url: 'https://api.github.com/organizations/XXXXXX/team/XXXXXX/memberships/n0bisuke' } すでに入っているもしくは招待に成功すると、acitveのステータスが返ってきます。 オーガナイゼーション外部の人を招待する場合は、一旦メールがユーザーに飛び、ユーザーが許可するとチームにも追加されるという流れなので、最初はpendingのステータスになると思います。 まとめ こんな感じでオーガナイゼーション招待&チーム追加ができました。 ユーザーにはメールが飛んでいるので、オーガナイゼーションに参加してもらいます。ユーザーが参加ボタンを押すことでオーガナイゼーションにやっと追加されるので、追加後にはユーザーに確認を入れると良さそうですね。 実際の運用だと、こんな感じでDiscordのBOTから呼び出せるようにしてみています。 便利だ。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インタープリタを作る その18

概要 インタープリタを作ってみた。 avrインタープリター書いてみた。 avr studio4で、動作を確認した。 投入したソース ldi r16, 0x00 ldi r31, 0x30 inc r16 inc r31 cpi r16, 0x09 brne PC - 3 写真 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初歩】JavaScriptの読み込み console出力 HelloWorld!

①html内でjavascriptを読み込む <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- htmlの中にjavascriptを読み込む場合 --> <script> console.log('Hello World!'); </script> <!-- htmlの中にjavascriptを読み込む場合 --> </body> </html> ②別のフォルダでscript.jsを読み込む場合 ・jsフォルダの中にscript.jsを作ります。 ・script.jsに記述 src属性でscript.jsのフォルダを読み込みます。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- jsフォルダでjavascriptを読み込む場合 --> <script src="js/script"></script> <!-- jsフォルダでjavascriptを読み込む場合 --> </body> </html> ・index.htmlを読み込んで、検証(option + command + I) consoleを選択してHelloWorld!と出てればOKです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】動的なtable生成、tdに動的なselectを生成

やりたいこと tableの行を動的に追加。 さらにoptionも配列から動的に追加 想定 配列はDBから取得。DBが変われば、option選択肢も動的に変更されるようにする ※本当はjqueryを使ったほうがみやすくすっきりしますが、あえてjavascriptで書きます。  jqueryでの記述バージョンもそのうちアウトプットしようと思います。 下記をもっとシンプルに分解した記事 【javascript】シンプルな動的selectの生成、option(選択肢)の追加 【javascript】シンプルなtableの動的行追加・削除(ボタンクリックで行追加・削除) 【javascript】シンプルな動的tableのinputの値取得 完成形、動作確認(ここでは配列をあらかじめ設定) See the Pen js table td→input by Hirofumi Sato (@hfmst) on CodePen. コード 下記、データ取得については別途投稿します。 index.html <div> <button onclick="addrow()">行追加</button> <button onclick="getdt">送信</button> <button onclick="getdt">取得</button> </div> <table border="1" id="tbl"> <tr> <th>日付</th> <th>担当</th> <th>タスク</th> </tr> </table> js.html function addrow(){ let tbl = document.getElementById('tbl'); let name=["山田太郎","斎藤花子","最上祐樹"]; let todo=["メール対応","会議","資料作成","掃除"]; //input type=dateをtrに追加 let tr = document.createElement('tr'); let datetd = document.createElement('td'); let dateinp = document.createElement('input'); //↑上記で必要な要素(tr,td,input)を用意 dateinp.setAttribute('type','date');//inputを日付形式に datetd.appendChild(dateinp); //tdに追加 tr.appendChild(datetd); //下記、createSelect関数に、配列、tr、tblを渡す createSelect(name,tr,tbl); createSelect(todo,tr,tbl); tbl.appendChild(tr); } //担当とタスクは同じくselectなので、createSelectを使いまわします。 function createSelect(arr,tr,tbl){ let sl = document.createElement('select'); let td = document.createElement('td'); for(let num in arr){ //引数で受け取ったからoptionを作って動的にselect生成 let op = document.createElement('option'); op.text = arr[num]; sl.appendChild(op); } td.appendChild(sl); tr.appendChild(td); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Jest + jsdomでCanvas要素を単体テストする

はじめに この記事は、Jest(jsdom)でContext2Dインターフェイスを利用するCanvas要素の単体テスト方法を記録、共有するためのものです。 想定する読者 この記事は、以下の読者を想定して書かれています。 JavaScriptの開発経験がある Jestを使ったことがある JavaScriptの解説やJestのインストールガイドはこの記事には含まれません。 想定する環境 この記事は、以下の環境を想定して書かれています。記事を読む前に、お手元の環境をご確認ください。 $ node --version v16.3.0 $ npm --version 7.15.1 また、この記事で扱うパッケージは以下の通りです。 ▼package.json "devDependencies": { "canvas": "^2.8.0", "jest": "^27.0.4", "pixi.js-legacy": "^6.0.4", } WebGLの単体テストは想定していません。WebGLコンテンツをテストしたい場合、Puppeteerの導入を検討してください。 参考記事 : JestでPuppeteerを動かしてCIで実行する 先に結論だけ JestでCanvas要素をテストする最小限のリポジトリを作りました。 JestとCanvas Jestは、ブラウザ環境を想定したテストのためにjsdomを内包しています。jsdomとはDOMをJavaScriptで実装したものです。Pure JavaScriptで実装されているため、node.js上で動作します。jsdomを通じて、ユーザーはテストに必要なDOMを組み立てて操作します。 jsdomのCanvasサポート jsdomはテストやスクレイピングを目的としています。そのためjsdom単体ではCanvas要素をサポートしていません。Canvas要素をDOMツリーに追加しようとすると、jsdomはdiv要素を代わりに挿入し、処理を簡略化します。 jsdomでCanvas要素をサポートする場合、node-canvasを追加します。 jsdom README : Canvas support jsdom includes support for using the canvas package to extend any elements with the canvas API. To make this work, you need to include canvas as a dependency in your project, as a peer of jsdom. jsdomには、canvasパッケージを使用して任意の要素をcanvas APIで拡張するためのサポートが含まれています。これを動作させるには、jsdom のピアとして、プロジェクトに canvas を依存関係として含める必要があります。 jsdomはnode-canvasがパッケージ内にインストールされていることを自動で認識します。ユーザーがなにか設定する必要はありません。node-canvasがインストールされている場合、JestはCanvasに関わる処理をnode-canvasに渡します。 Canvasのテスト それでは実際にCanvasをテストしてみます。今回はCanvas描画ライブラリとしてPixiJSの2Dコンテキスト対応版pixi.js-legacyを使います。 モジュールのインストール プロジェクトにJestとnode-canvas、pixi.js-legacyをインストールします。 npm install --save-dev jest canvas pixi.js-legacy npm v7以降の場合 npm v7から、peerDependenciesに指定されたモジュールが自動的にインストールされるようになりました。jsdomはpeerDependenciesにnode-canvasを指定しています。そのため、node-canvasを個別にインストールする必要はありません。 テストの作成 テストファイルを作成します。 ▼./__test__/Test.spec.ts jest.spyOn(console, "error").mockImplementation() describe("Test", () => { const PIXI = require("pixi.js-legacy"); jest.spyOn(console, "log").mockImplementation((x) => x); const app = new PIXI.Application({ width: 640, height: 480, forceCanvas: true, }); document.body.appendChild(app.view); test("app should be exist", () => { expect(app).toBeTruthy(); }) }) テスト環境を指定して実行 Jestの設定ファイルを作成し、環境にjsdomを指定します。 ▼jest.config.js module.exports = { testEnvironment: "jsdom", }; もしくは、jestコマンドに--env=jsdomオプションを追加します。 ▼package.json "scripts": { "test": "jest --env=jsdom" } テスト結果 > minimal-test-environment-jest-pixijs@0.1.0 test > jest --env=jsdom PASS __test__/Test.spec.js Test ✓ app should be exist (2 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.393 s Ran all test suites. プロセスは終了コード 0 で終了しました テストがパスすれば成功です。 以上、ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptにおけるデザインパターン2(構造系)

デザインパターンを整理する デザインパターンを次の3つに分けて考えます 作成系デザインパターン (コンストラクター、ファクトリー、シングルトンなど) 構造系デザインパターン (デコレータ、ファサードなど) 振舞い系デザインパターン (イテレータ、メディエータ、オブザーバーなど) 構造系デザインパターン Learning JavaScript Design Patternsより 構造パターンはオブジェクトの構成に関係しており、通常、異なるオブジェクト間の関係を実現する簡単な方法を識別します。それらは、システムの一部が変更されたときに、システムの構造全体が同じことをする必要がないことを保証するのに役立ちます。また、特定の目的に適合しないシステムの部分を適合するものに作り直すのにも役立ちます。 デコレータパターン デコレータパターンは、オブジェクトの機能を拡張するということに注目し、プロトタイプの継承に頼るのではなく、decoratorクラスのオブジェクトにラップすることで装飾します。 class Goods { constructor(name, price, describe) { this.name = name this.price = price this.describe = describe } getGoods() { return this.name } getPrice() { return this.price } getdescribe() { return this.describe } } class Discount { constructor(item) { this.item = item } getGoods() { return '【半額】' + this.item.getGoods() } getPrice() { return this.item.getPrice() + '円 -> ' + this.item.getPrice() / 2 } getdescribe() { return this.item.getdescribe() } } class Recommendation { constructor(item) { this.item = item } getGoods() { return '【オススメ】' + this.item.getGoods() } getPrice() { return this.item.getPrice() } getdescribe() { return '*' + this.item.getdescribe() + '*' } } class Few { constructor(item) { this.item = item } getGoods() { return '【残りわずか!】' + this.item.getGoods() } getPrice() { return this.item.getPrice() } getdescribe() { return this.item.getdescribe() } } function printGoods(item) { console.log(`商品: ${item.getGoods()}`) console.log(`価格: ${item.getPrice()}円`) console.log(`詳細: ${item.getdescribe()}`) } let goods = [ new Goods('パソコン', 50000, '普通のパソコンです'), new Recommendation(new Goods('高機能パソコン', 100000, '処理速度が早いです')), new Discount(new Goods('傷ありパソコン', 50000, '傷はあるけど使えます')), new Recommendation(new Few(new Discount(new Goods('有名メーカーパソコン', 120000, '某メーカーのパソコンです')))) ] for (let i = 0; i < goods.length; i++) { printGoods(goods[i]) console.log('\n') } // 結果 // 商品: パソコン // 価格: 50000円 // 詳細: 普通のパソコンです // 商品: 【オススメ】高機能パソコン // 価格: 100000円 // 詳細: *処理速度が早いです* // 商品: 【半額】傷ありパソコン // 価格: 50000円 -> 25000円 // 詳細: 傷はあるけど使えます // 商品: 【オススメ】【残りわずか!】【半額】有名メーカーパソコン // 価格: 120000円 -> 60000円 // 詳細: *某メーカーのパソコンです* 例のようにnewでクラスの付け外しをするだけで装飾することができます。 ファサードパターン Learning JavaScript Design Patternsより ファサードは、jQuery などの JavaScript ライブラリでよく見られる構造パターンであり、実装は幅広い動作のメソッドをサポートする場合がありますが、これらのメソッドの「ファサード」または限定された抽象化のみが使用のために公開されます。 function intro() { return { printIntro: function () { console.log('初めまして。') } } } function main() { return { printMain: function () { console.log('これはファサードの説明です。') } } } function end() { return { printEnd: function () { console.log('ご静聴ありがとうございました。') } } } var Speech = { print: function () { var o1 = new intro() var o2 = new main() var o3 = new end() o1.printIntro() o2.printMain() o3.printEnd() } } Speech.print() // 結果 // // 初めまして。 // これはファサードの説明です。 // ご静聴ありがとうございました。 例のような形に限られたことではないですが、複数の機能をまとめたSpeechのことをファサードといえます。ファサードパターンはいたる所で使われています。 参考文献 Learning JavaScript Design Patterns 関連記事 JavaScriptにおけるデザインパターン1(作成系) JavaScriptにおけるデザインパターン3(振舞い系)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptにおけるデザインパターン(構造系)

デザインパターンを整理する デザインパターンを次の3つに分けて考えます 作成系デザインパターン (コンストラクター、ファクトリー、シングルトンなど) 構造系デザインパターン (デコレータ、ファサードなど) 振舞い系デザインパターン (イテレータ、メディエータ、オブザーバーなど) 構造系デザインパターン Learning JavaScript Design Patternsより 構造パターンはオブジェクトの構成に関係しており、通常、異なるオブジェクト間の関係を実現する簡単な方法を識別します。それらは、システムの一部が変更されたときに、システムの構造全体が同じことをする必要がないことを保証するのに役立ちます。また、特定の目的に適合しないシステムの部分を適合するものに作り直すのにも役立ちます。 デコレータパターン デコレータパターンは、オブジェクトの機能を拡張するということに注目し、プロトタイプの継承に頼るのではなく、decoratorクラスのオブジェクトにラップすることで装飾します。 class Goods { constructor(name, price, describe) { this.name = name this.price = price this.describe = describe } getGoods() { return this.name } getPrice() { return this.price } getdescribe() { return this.describe } } class Discount { constructor(item) { this.item = item } getGoods() { return '【半額】' + this.item.getGoods() } getPrice() { return this.item.getPrice() + '円 -> ' + this.item.getPrice() / 2 } getdescribe() { return this.item.getdescribe() } } class Recommendation { constructor(item) { this.item = item } getGoods() { return '【オススメ】' + this.item.getGoods() } getPrice() { return this.item.getPrice() } getdescribe() { return '*' + this.item.getdescribe() + '*' } } class Few { constructor(item) { this.item = item } getGoods() { return '【残りわずか!】' + this.item.getGoods() } getPrice() { return this.item.getPrice() } getdescribe() { return this.item.getdescribe() } } function printGoods(item) { console.log(`商品: ${item.getGoods()}`) console.log(`価格: ${item.getPrice()}円`) console.log(`詳細: ${item.getdescribe()}`) } let goods = [ new Goods('パソコン', 50000, '普通のパソコンです'), new Recommendation(new Goods('高機能パソコン', 100000, '処理速度が早いです')), new Discount(new Goods('傷ありパソコン', 50000, '傷はあるけど使えます')), new Recommendation(new Few(new Discount(new Goods('有名メーカーパソコン', 120000, '某メーカーのパソコンです')))) ] for (let i = 0; i < goods.length; i++) { printGoods(goods[i]) console.log('\n') } // 結果 // 商品: パソコン // 価格: 50000円 // 詳細: 普通のパソコンです // 商品: 【オススメ】高機能パソコン // 価格: 100000円 // 詳細: *処理速度が早いです* // 商品: 【半額】傷ありパソコン // 価格: 50000円 -> 25000円 // 詳細: 傷はあるけど使えます // 商品: 【オススメ】【残りわずか!】【半額】有名メーカーパソコン // 価格: 120000円 -> 60000円 // 詳細: *某メーカーのパソコンです* 例のようにnewでクラスの付け外しをするだけで装飾することができます。 ファサードパターン Learning JavaScript Design Patternsより ファサードは、jQuery などの JavaScript ライブラリでよく見られる構造パターンであり、実装は幅広い動作のメソッドをサポートする場合がありますが、これらのメソッドの「ファサード」または限定された抽象化のみが使用のために公開されます。 function intro() { return { printIntro: function () { console.log('初めまして。') } } } function main() { return { printMain: function () { console.log('これはファサードの説明です。') } } } function end() { return { printEnd: function () { console.log('ご静聴ありがとうございました。') } } } var Speech = { print: function () { var o1 = new intro() var o2 = new main() var o3 = new end() o1.printIntro() o2.printMain() o3.printEnd() } } Speech.print() // 結果 // // 初めまして。 // これはファサードの説明です。 // ご静聴ありがとうございました。 例のような形に限られたことではないですが、複数の機能をまとめたSpeechのことをファサードといえます。ファサードパターンはいたる所で使われています。 参考文献 Learning JavaScript Design Patterns 関連記事 JavaScriptにおけるデザインパターン(作成系)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IE非対応表示に関してベストプラクティスを考える

?課題 IEの利用者向けに「IEは非対応です。別のブラウザをお使い下さい」という表示をしようと思います。ところがIEの判定ルーチン部分や画面表示に関してはIEで処理できる必要があり、Webpack導入済みの環境で真面目にこれをやろうとすると、IE対応の必要なファイルとそうでないファイルを切り分けて云々……とする必要があります。 IE判定なんて複雑なものでもなし、告知画面そのものは所謂ペライチでJSすら使わないレベルなのに、これは面倒or本末転倒……っていうのが今回解決したい課題となります。 ?結論 そもそもIE判定及び告知画面についてはWebpackで扱わず、手打ちのHTML,CSS,JSファイルを作ってwebpackの出力先フォルダに突っ込んだ方が楽なのでは。 babel関係も不要で、Gitの無視ファイル設定だけちょこっと弄るだけですし。 手順 1. IE判定を行い、非対応の告知画面ページへ遷移するルーチンを書いたJSファイルを作る const isIe = function (userAgent) { return (userAgent.indexOf('msie') != -1 || userAgent.indexOf('trident') != -1) } if (isIe(window.navigator.userAgent.toLowerCase())) { location.href = "【警告画面のHTMLファイルのパス】" } もちろん、ここでDOMを書き換えて告知画面を出してもいいのですが、 何かの拍子にwebpackでバンドルしたjsと干渉しそうで不安 書き換え処理のJSもIE11対応する必要がある 告知画面のHTMLファイルは要件の性質上、直書きできる可能性が高く、この場合エディタの補完が効く という点を考慮して、告知画面は別ファイルに切り出してます。 それからIE11でもconstは使えます。 2. メインとなるHTMLファイルのheadタグ内にWebpackで生成したファイルより先に記述する <head> <script type="text/javascript" src="【IE判定&遷移ルーチン(要IE11対応)】.js"></script> <script type="text/javascript" src="【Webpackで作ったファイル】.js"></script> </head> 3.非対応の告知画面はざっくり手打ちの静的ファイルだけで構成 「IEは非対応です。別のブラウザ使ってください」という旨の表示以外何もしようがないので、手打ちHTMLとCSSだけで何とかなる範疇かと。HTMLファイル内に全部書いてしまってもいいかもしれませんね。 もうちょっとユーザーフレンドリーにするなら、エラー画面を見ているユーザーはWindowsユーザーかつEdgeをインストール済みであることが期待できるので、「Edgeで開く」リンクを置いておくといいと思います。 マイナーなテクニックですが、Windowsの場合、レジストリにパラメータを登録しておくと、ブラウザからURLスキームを使ってインストールしてあるソフトを呼び出すことができるんですね。 そしてedgeに関してはインストールした時に登録済みなので、 ​<a href="microsoft-edge:【edgeで開かせたいURL】">Edgeで開く</a>​​​​​ こういうリンクを踏ませるだけでedgeで開かせることができます。 ただまぁメジャーなChromeじゃなくてマイナーなEdgeを薦めるのはどうか、という葛藤もありますが、IE11を使ってるユーザー相手ですとねぇ……。B2Bで官公庁やITとは縁遠い業界相手になるほど刺さるかと。 またEdgeのインストールすらブロックしている法人の話もちらほら聞くので注意書きがあってもいいかもしれません?‍♂️ 備考 告知画面の表示ですが手抜きしすぎて、適当な背景+画面のど真ん中に「Internet Explorerはサポート外です。別のブラウザをお使い下さい」という表示を出すだけだと、怪しげなフィッシングサイトに飛ばされた感が半端ないです? 背景ぐらいは通常サイトに揃えるなり、一緒に会社ロゴを表示するなり、多少なり公式アピールをした方がいいです。 参考 使用してるブラウザを判定したい - Qiita Microsoft EdgeでWebページを開くインターネットショートカット 初心者備忘録
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】シンプルな動的selectの生成、option(選択肢)の追加

やりたいこと 一次元配列からselectの選択肢を動的に作成 中身 selectにondblclickクリックで、optionをselectに追加 See the Pen createselect by Hirofumi Sato (@hfmst) on CodePen. コード index.html <select id="test" ondblclick="create_op()"></select> js.html function create_op(){ let arr = ["赤","青","緑","黒","白"]; //適当な配列用意 let sl = document.getElementById('test'); //対象のselect取得 if(sl.length<arr.length){ //selectが空の時のみ関数実行 for(let num in arr){ //arrの要素数を0から順にnumに入れて繰り返し処理 let op = document.createElement('option'); //optionを新しく毎回作る op.text = arr[num]; //optionのテキストに配列[num番目]の値を入れる sl.appendChild(op); //optionをselectに追加 } } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

resizeもしくはwindow.matchMediaを用いてウィンドウの幅に合わせてJavascriptの処理を変える方法

はじめに こんにちは。 私はフロントエンジニアとして働いていますが、未経験であるため現在課題を出されています。 その課題で「ウィンドウの幅に合わせてJavascriptの処理を変えたい!」ということがあったのでその方法を書いておきます。 jQueryのresizeを使用した方法 まず、方法として考えられるのがjQueryのresizeメソッドです。 resizeはウィンドウの幅が変わると実行するメソッドで、ウィンドウの幅に合わせて処理を変えたい時に使用できます。 $(window).resize(function(){ //windowの幅をwindow_widに代入 let window_wid = $(window).width(); //windowの分岐幅をmdに代入 let md = 1024; if (window_wid >= md) { //md以上の処理 }else{ //md未満の処理 } }) 上記のようにコードを書くとウィンドウの幅に合わせて処理を変えることができます。 しかし、大きなデメリットがあります。 それは、ウィンドウのサイズが変わるたびにこの処理が実行されてしまうことです。 resizeはウィンドウのサイズが変わるたびに発火するので、無駄が多いです。 window.matchMedia もう一つの方法としてwindow.matchMediaを用いた方法があります。 こちらを使用することでブレークポイントを通過した時のみ処理を走らせることが可能です。 無駄が無くなることと、cssと同じ指定ができることがメリットとして挙げられます。 const md = window.matchMedia('(min-width: 1024px)'); function checkWindow(wid){ if (wid.matches) { //min-width: 1024pxに合致する処理 } else { //min-width: 1024pxに合致しない処理 } } //load時にも処理を走らせる。 checkWindow(md); md.addListener(checkWindow); 終わりに ブレークポイントで処理を分けて実行したい場合にはwindow.matchMediaが便利かなっと思います。 resizeでも工夫をすればブレークポイントを通過したときだけ処理を実行することが可能なようですが、どうしても必要なとき以外はwindow.matchMediaで問題ないかと思います。 参考文献 window.matchMediaによる、メディアクエリに応じたJavaScriptの実行 window.matchMedia をそろそろ活用してもいい頃
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ファイルダウンロードのAPIリクエスト送信を実装してみたら無限ループになった件

問題 ダウンロードボタンを一回押したら、無限に自動ダウンロードすることになりました <a id="id1" href="javascript:void(0)" onclick="handleDownload('/', 1)">ダウンロード</a> const downloadFile = (path, params) => new Promise((resolve, reject) => { axios({ url: path, method: 'GET', responseType: 'blob', params: params, }).then((res) => { const url = URL.createObjectURL(new Blob([res.data], { type: 'text/csv' })); const link = document.getElementByID('id1'); link.href = url; const filename = 'filename'; //なんらかのファイル名処理 link.setAttribute('download', `${filename}.csv`); link.click(); URL.revokeObjectURL(url); }).then((res) => { resolve(res); }).catch((e) => { reject(e); }); }); const handleDownload = (path, id) => { const params = { id: id, } await downloadFile(path, params).catch((e) => window.alert(e)); 原因 ボタン押下する → onclickイベント着火 → handleDownload実行 → link.click()実行 → aタグのonclickイベント着火 → handleDownload実行 → link.click()実行 → aタグのonclickイベント着火... の無限ループに入ります! 解決方法 <span onclick="handleDownload('/', 1)">ダウンロード</span> /** * downloadFile関数の中でgetElementでaタグ要素を取得するのではなく、 * 代わりにjsの中でaタグ要素を作成して、ダウンロード実行の後に削除する */ const link = document.createElement('a'); ... document.body.appendChild(link); link.click(); URL.revokeObjectURL(url); link.parentNode.removeChild(link);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Javascript】戻り値が関数である関数(学習ノート)

初めに 関数を戻り値にする関数について学習した内容のoutput用記事です。 ※内容に間違いなどがある場合はご指摘をよろしくお願いします。 ※こちらの記事はあくまでも個人で学習した内容のoutputとしての記事になります。 試してみる 次のようにcalculatesという関数の戻り値が関数である場合を考えてみます。 const calculates = function (a, b) { return function (c) { console.log(a + b * c); } } calculatesに引数を1と2を渡し、変数exampleに格納します。この時、exampleはcという引数を取る関数になります。 const example = calculates(1, 2); //exampleはfunction(c)と同様 example(3); example(4); これはfunction(a,b)の戻り値はfunction(c)になるので連続して書くこともできます。 calculates(1,2)(3); calculates(1,2)(4); 結果は先ほどと同じです。 アロー関数を使えば、次のようにさらに短く書くことも可能です。 const calAttr = (a, b) => (c) => console.log(a + b * c); calAttr(1,2)(3); calAttr(1,2)(4); 参考サイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インタープリタを作る その17

概要 インタープリタを作ってみた。 avrインタープリター書いてみた。 条件分岐を動かす。ループしてみる。 方針 sregの内部表現に合わせる。 sreg フラグ sreg[0] c sreg[1] z sreg[2] n sreg[3] v sreg[4] s sreg[5] h sreg[6] t sreg[7] i cpi,breq,brneを実装する。 cpiの実装 zフラグのみ cpi: function(_Rd, K) { K = hen(K); var Rd = this.dataspace[_Rd]; var R = [false, false, false, false, false, false, false, false]; var SREG = this.dataspace[this.sreg]; R[0] = !!(Rd[0] ^ K[0]); R[1] = !!(Rd[1] ^ K[1]); R[2] = !!(Rd[2] ^ K[2]); R[3] = !!(Rd[3] ^ K[3]); R[4] = !!(Rd[4] ^ K[4]); R[5] = !!(Rd[5] ^ K[5]); R[6] = !!(Rd[6] ^ K[6]); R[7] = !!(Rd[7] ^ K[7]); SREG[1] = !R[7] && !R[6] && !R[5] && !R[4] && !R[3] && !R[2] && !R[1] && !R[0]; this.PC++; this.dataspace[this.sreg] = SREG; }, greqの実装 breq: function(k) { if (this.dataspace[this.sreg][1] === true) { this.PC = this.PC + k; } this.PC++; }, 投入したソース レジスタ16が、9になるまでループする。 レジスタ31の値が、0から9まで変化する。 avr.ldi(16, 0x00) avr.ldi(31, 0x30) avr.inc(16) avr.inc(31) avr.cpi(16, 0x09) avr.brne(-4) 実行結果 0123456789 成果物 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】シンプルな動的tableのinputの値取得

やりたいこと  table内のinputからの記事取得    下記参考でわかりやすく解説して下さってますが、inputと値が混同して条件分岐があったため、  ここではinputのみで、よりシンプルな例で解説しています。   ●ひとつ前の記事 javascriptでシンプルなtableの動的行追加・削除(ボタンクリックで行追加・削除) ●参考 【JavaScript】テキストボックスを含むTableからテキストを取得する 完成 二次元配列に値格納してます。二次元配列はconsoleからご確認下さい。 See the Pen table getdata by Hirofumi Sato (@hfmst) on CodePen. コード 前回との変更部分だけです。(input取得のみ) 行追加・削除は前の記事から確認ください。 js.html //inputデータ取得 function getdt(){ let vals = []; //二次元配列の変数用意 let alltr = tbl.querySelectorAll('tr'); //すべてのtr取得➡alltrに代入。ここはヘッダーもふくんでます。 alltr.forEach(tr=>{ //alltrから一つずつ取り出してtrにいれて処理 let alltd = tr.querySelectorAll('td'); //trからtd全部取得 let arr =[]; //空の一次元配列を作成(←ここにおいて、forEachで毎回初期化します。 alltd.forEach(td=>{ arr.push(td.firstElementChild.value); //td一つずつ取り出し、値取得してarrにpush }) vals.push(arr); }) vals.shift(); //ヘッダー削除 alert(vals); //確認用 console.log(vals); //確認用 return vals; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

kintoneとOutlookを連携してスケジュール管理をする#01

経緯 kintoneのOutlookを連携してスケジュール管理をしたい。 けど検索して出てくる記事が古いため、アレンジしてなるべく最新のものに対応する。 要するに「Outlook連携 - kintoneからOutlookスケジュールを登録しよう!!」のOutlook連携をほぼサンプルのまま使っていたのだけど、先日急に動かなくなったので最新化対応したいということ。 やりたいこと MSAL v2 に対応してkintoneとOutlookのスケジュールを連携させたい。 kintone UI Component v1 対応したUIを構築したい。 FullCalendar.js を導入してカレンダー表示させたい。 参考サンプル こちらの2つのサンプルを参考にOutlook連携カスタマイズを行います。 1. Outlook連携 - kintoneからOutlookスケジュールを登録しよう!! 2. クイックスタート: PKCE 対応の承認コード フローを使用して JavaScript SPA 内でユーザーをサインインさせ、アクセス トークンを取得する 今回(本記事)のゴール 一覧画面にkintone UI Component v1 対応したボタンを表示する。 フォームの設定 kintoneサンプルに記載の内容で構築します。 アプリストアからToDoアプリを作成し、イベントIDを文字列で追加、開始日と終了日を日付から日時に変更してください。 フィールド名 フィールドタイプ フィールドコード イベントID 文字列(1行) EventId ToDo名 文字列(1行) To_Do 担当者 ユーザー選択 Assignees 優先度 ドロップダウン Priority 締切日 日付 Duedate 開始日時 日時 From 終了日時 日時 To 詳細内容 文字列(複数行) Details 添付ファイル 添付ファイル Attachments 登録するカスタマイズJS/CSS javascript https://unpkg.com/kintone-ui-component/umd/kuc.min.js https://js.cybozu.com/jquery/3.3.1/jquery.min.js buttonSettings.js ui.js css buttons.css ソース ボタン表示用の設定情報です。 内容はkintoneのサンプルのままです。 変更点は表示するボタンに対してclass指定をしています。 butttonSettings.js window.buttonSettings = { lang: { en: { button: { signIn: 'Sign in Outlook', signOut: 'Sign out of Outlook', addEvent: 'Add Event', getEvent: 'Get Event', setToday: 'Set Today', registerExec: 'Add', updateExec: 'Update', deleteExec: 'Delete', cancelExec: 'Cancel' }, message: { info: { confirmRegister: 'Do you want to add this event to Outlook?', confirmUpdate: 'Do you want to update this event in Outlook?\n (kintone Record will be registered.)', confirmDelete: 'Do you want to delete this event from Outlook?' }, warning: { noEvent: 'The target event does not exist in Outlook.' }, success: { registerExec: 'Your event has been added successfully.', updateExec: 'Your event has been updated successfully.', deleteExec: 'Your event has been deleted successfully.' }, error: { registerFailure: 'Failed to add your event.', updateFailure: 'Failed to update your event.', deleteFailure: 'Failed to delete your event.', signInFailure: 'Failed to sign in Outlook.', getAccessTokenFailure: 'Failed to get access token.', fromtoDatetimeNodata: 'Start date/time or end date/time has not been entered.', fromDatetimeFuture: 'Start date/time is not earlier than end date/time.', addAttachFileFailure: 'Failed to add attachments.', updateAttachFileFailure: 'Failed to update attachments.' } } }, ja: { button: { signIn: 'Outlookにログイン', signOut: 'Outlookからログアウト', addEvent: '予定を登録', registerExec: '登録', updateExec: '更新', deleteExec: '削除', cancelExec: 'キャンセル' }, message: { info: { confirmRegister: 'Outlookに登録しますか?', confirmUpdate: 'Outlookを更新しますか?\n (kintoneにはレコードが登録されます)', confirmDelete: 'Outlookから削除しますか?' }, warning: { noEvent: '対象の予定がOutlookに存在しません' }, success: { registerExec: 'Outlookに登録しました', updateExec: 'Outlookを更新しました', deleteExec: 'Outlookから削除しました' }, error: { registerFailure: 'Outlookの登録に失敗しました', updateFailure: 'Outlookの更新に失敗しました', deleteFailure: 'Outlookの削除に失敗しました ', signInFailure: 'サインインできませんでした', getAccessTokenFailure: 'アクセストークンが取得できませんでした', fromtoDatetimeNodata: '開始日時または終了日時が未入力です', fromDatetimeFuture: '開始日時が未来日時になっています', addAttachFileFailure: '添付ファイルの登録に失敗しました', updateAttachFileFailure: '添付ファイルの更新に失敗しました' } } } }, setting: { lang: 'ja', i18n: {}, ui: { buttons: { signInOutlook: { text: 'signIn', type: 'submit', className: 'header-not-signed' }, signOut: { text: 'signOut', type: 'normal', className: 'header-signed' }, sendEvent: { text: 'addEvent', type: 'submit', className: 'header-signed' } } } }, }; ボタン表示の処理をします。 表示用の定義ファイルを読込み、ログインユーザーの言語設定に合わせてボタンの表示を行います。 ui.js jQuery.noConflict(); (function ($) { 'use strict'; // ボタンの表示情報を取得 var BS = window.buttonSettings; // カスタマイズのメイン処理 var uiService = { setting: { lang: {}, i18n: {}, ui: {} }, data: { ui: {}, isLoginOutlook: false }, // 初期処理 init: function () { // ログインユーザーの言語設定を取得 this.setting.lang = kintone.getLoginUser().language || 'ja'; this.setting.i18n = this.setting.lang in BS.lang ? BS.lang[this.setting.lang] : BS.lang.en; this.setting.ui = BS.setting.ui; }, // ボタン表示設定 uiCreateForIndex: function (kintoneHeaderSpace) { if (typeof kintoneHeaderSpace === 'undefined') { return; } if (this.data.ui.HeaderSigned !== undefined || this.data.ui.HeaderNotSigned !== undefined) { return; } // サインインボタン表示 this.data.ui.HeaderNotSigned = document.createElement('div'); this.data.ui.btnSignIn = this.createButton(this.setting.ui.buttons.signInOutlook, this.setting.i18n.button); this.data.ui.HeaderNotSigned.appendChild(this.data.ui.btnSignIn); kintoneHeaderSpace.appendChild(this.data.ui.HeaderNotSigned); }, // ボタンを作成 createButton: function (setting, lang) { if (typeof setting === 'undefined' || !setting) { return null; } var uiButton; var text = lang ? lang[setting.text] || setting.text || '' : setting.text || ''; var type = setting.type; var className = setting.className ? setting.className : '' ; uiButton = new Kuc.Button({ text: text, type: type, className: className }); return uiButton; }, }; // 画面表示時イベント kintone.events.on('app.record.index.show', function (event) { // 初期処理 uiService .init(); // ボタンを表示 uiService .uiCreateForIndex(kintone.app.getHeaderSpaceElement()); }); })(jQuery); kintoneサンプルではjsでstyleを追加していましたが、Kucではclassまたはidを付与して設定します。 classの付与はjsのボタン生成時に行います。 buttons.css .header-not-signed > button { display: inline-block; margin: 0 15px 15px 15px; } ボタンが表示されました まだ何も動きません。 次回 ボタンを押下した際にログインするようにします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitHubの活動履歴を捏造するアプリを作ったよ

クソアプリ駆動開発中のもぐみです。 この世に無駄なアプリを量産するべくこの活動をひっそり行なっていました。 でも人生に無駄って必要だと思うんですよ。 無駄こそが人生を豊かにすると思います。 それはいいとして。 今回作ったアプリ 自分のGitHubの活動履歴、めっちゃ草生えてる! 自分めっちゃ開発してる!えらい! ・・・という気分を味わうための、GitHubの活動履歴を捏造するアプリを作りました。 使い方は簡単で、草を生やしたい部分をクリックすると緑に変わります。 クリックするごとに濃くなってめっちゃ開発してる人になります。 ・・・ただそれだけです(ヤケ) ほら見て!めちゃくちゃ開発してる!えらい!(※コラージュ) コードもクソ汚いんですが公開しておきます 最後に ちなみにクソアプリ開発は今後も続く予定なので、次回作をお楽しみに! 〜弊社の宣伝〜 火曜午前は技術研究の時間に充てられていて有志で開発できるよ! もぐみと一緒にクソアプリを作りませんか? https://www.person-link.co.jp/ おしまい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GoogleAppsScriptを用いた学生実験レポートの自動化

はじめに プログラミングを用いて学生実験のデータ加工からグラフ作成まで自動化する手法を紹介します。 この記事は、授業でC言語は触ったことある!くらいのひとを対象に描きます。 しかしながら、GoogleAppsScriptに関する記事はネット上に少ないようなので、レポートの自動化以外の場面でも応用が効くと思います。 用意するもの GoogleSpreadSheet 実験データ 楽をするぞ!という気持ち 実験データはGoogleSpreadSheetに保存するようにしてください。GoogleSpreadSheetはマイクロソフトが提供するExelのGoogle版みたいなものです。 今回はこんなデータを用いました。周波数に対して色々な値をかけたりルートを取ったりして、理論値(単位:dB)を求めます。 自動化する上でのコツ 計算を自動化する上でのコツは、自分で計算した方が早いところは自分の手で計算することです。(当たり前かもしれませんが笑) 今回であれば次のような回路のインピーダンス、電気系以外の人向けの言い換えると回路抵抗を求め、いくつかの加工を施した後に$K=\frac{Zf}{Zs}$としてKの値を求め、$20log|K|$を取ることで理論値であるデシベルを求めます。 電気系以外の人もこの記事を読むことをを想定しているので細かいところは省きますが、ZfはC,Rf1,Rf2を用いて次のような式で表されます。 $Zf=\frac{Rf2(Rf1+\frac{1}{jC\omega})}{Rf2+(\frac{1}{jC\omega}+1)}$ このとき、式には虚数単位(j)が混じっており、このZfの絶対値をそのまま計算するプログラムを書くのは、できないことはないですがちょっとめんどくさいです。 そこでZfを次のように変形します。 $Zf=\frac{Rf2(Rf1+\frac{1}{jC\omega})}{Rf2+(\frac{1}{jC\omega}+1)}=\frac{Rf1+Rf1Rf2(Rf1+Rf2)(C\omega)^2+jCRf1^2\omega}{1+((Rf1+Rf2)C\omega)^2}$ ちょっと複雑になりましたが、これだったら$|Zf|=\sqrt{Re(Zf)^2+Im(Zf)^2}$で計算可能なのでプログラムを書くのが楽になりました。 プログラムで計算を自動化 では、いよいよ自動化するプログラムを書きます。GoogleSpreadSheet→ツール→スクリプトエディタと移動していきます。 そうすると、GoogleAppsScriptのページに移動するはずです。 GoogleAppsScriptとは、JavaScriptベースのスクリプト言語で、ドキュメント、​スプレッドシート、スライド、フォームなどのG Suiteサービスをカスタマイズ、拡張できます。 すると次のようなコードがあらかじめ記述されていると思います。 function myFunction() { } このフォーマットに沿ってコードを書いていきます。 今回は、Zs,Rf1,Rf2,C,$\omega=2\pi f$を用いてデシベルの理論値を計算するプログラムを書きます。 このプログラムは次の通りになります。 C言語で関数を書くことが出来れば難しくはないと思います。 今回は私のレポートを題材にしてQiitaを執筆しているので、以下のコードはみなさんの必要に応じて変更してください。 getDecibel.js //周波数を引数にとってデシベルをreturnする関数 function getDecibel(frequency) { //実験時に用いた各定数はconstで宣言 const Rf1 = 100000; const Rf2 = 10000; const Zs = 1000; const C = 0.0000000047; const w = 2*Math.PI*frequency; //Zfを求めるのに必要な分母と分子の計算 const denominator = 1+getSquare((Rf1+Rf2)*w*C); const numerator = getSqrt(Rf1+Rf1*Rf2*(Rf1+Rf2)*getSquare(w*C),w*C*getSquare(Rf1)); Zf = numerator/denominator; K = Zf/Zs; dB = 20*Math.log10(K); return dB; } //getDecibelに用いるサブ関数 function getSqrt(x,y) { z = Math.sqrt(x*x + y*y); return z; } //getDecibelに用いるサブ関数 function getSquare(x) { return x*x; } GoogleSpreadSheetのセルから値を持ってくる getDecibel関数では、周波数を引数にとってデシベルの理論値を計算して返しています。 GoogleSpreadSheetの各周波数値を関数にいちいち代入してもいいですが、せっかくなので値をGoogleSpreadSheetから取ってきて、関数に代入し、GoogleSpreadSheetに代入するところまで自動化してしまいましょう。 そこで、次のような関数を書きます。 putValuesToSheet.js function putValuesToSheet() { var gss = SpreadsheetApp.getActiveSheet(); for (let i = 3;i < 22; i++) { var cell = gss.getRange(i,4); var f = gss.getRange(i,2).getValue(); cell.setValue(getDecibel(f)); } } C言語では変数名を必ず宣言するので、varやconstという書き方に違和感を覚えてた人がいるかもしれません。 これらは、var(=variable)やconstと宣言し名前を付ければ、どんな値が代入されるかでコンピューターが都合のいいように解釈してくれるという仕組みに基づいているものだと思っていただいて構いません。 それらを踏まえて、putValuesToSheet関数を見てみます。 まずgssという変数にSpreadsheetApp.getActiveSheet()を用いて対応するGoogleSpreadSheetを紐づけています。 その後、gssのi行4列目のセルをcellという変数に対応させ、fに対してgetRange()とgetValue()でi行2列目から周波数の値を取ってきています。 最後に、setValue()を用いて対応させたcellに対して値を書き込んでいます。getDecibel()には、fに保存していたGoogleSpreadSheetに書き込んである周波数値を代入して、getDecibel()の戻り値であるデシベルの理論値を書き込むという仕組みです。 全体をfor文を用いてループしていて、1行づつgetDecibel()の計算と計算結果の書き込みが行われています。 実行結果 実行結果は次のようになりました。 グラフもプログラムで書くことができますが、今回は割愛します。 C列の実験値とD列の理論値がほとんど一緒でした! さいごに こんな感じに綺麗に自動化できるとプログラミング学んでいてよかったなぁって思います! この記事が、ここまで読んでくださった方の役に立てば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Gatsby】え?令和に手動でrel="noopener"付けてるの?それはもうチョベリバ!

はじめに こんにちは。先日、知らないうちにゆいレールが延伸しててびっくりしました、しかも最近とかではなく、結構前に...。沖縄に行かなきゃ!筆者です さて、先日以下の記事を書いたわけですが、対応として、Contentfulで管理している記事に対して、全記事、ぺちぺち手動で追加して対応したのですが、なんかそれくらいスクリプトでできる気がした次第です。 そして、それくらい先人の方々が既に行っているのでは と思ったら、案の定見つけましたので、記事にします! 自分のように運用でカバーみたいなことする人が1人でも減ることを切に願っております 外部リンクに自動でrel="noopener"付けるよ! これで実現できます! 1. まずは以下パッケージのインストール. npmの方 $ npm install gatsby-remark-external-links yarnの方 $ yarn add gatsby-remark-external-links 2. gatsby-config.js 編集. noopener未対応ブラウザのために、noreferrerも付けました gatsby-config.js module.exports = { plugins: [ { resolve: `gatsby-transformer-remark`, options: { plugins: [ { resolve: `gatsby-remark-external-links`, options: { rel: 'noopener noreferrer' } }, ], }, }, ], }; 3. build buildしましょう おわりに いやー、自動って素晴らしい 手動なんて大っ嫌いだぜ! それでは!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

シシドカフカジェネレータを作る上で得られた知見

シシドカフカジェネレータを作るうえで得た知見を、夜中に作りたいものを思いついてしまったときの知見と共にメモします。 開発の進め方 最小の構成から作る ボタンを押したらテキストエリアに何かがでるモノ 「シドカフ」から無作為に取ってきて6文字作るモノ 文字数、文字プールを指定できるモノ 絵文字対応 という流れで作りました。1ができてなきゃ2も実現できないので、基礎から作っていくというのは当たり前のことです。 基礎を作る作業が面倒なので「3」を目指して作り始めがちでした。そういう場合は大抵途中で力尽きます。作ろうとしているものが(見かけ上)大きすぎるので、途方にくれてしまいます。 夜中に始めたので、途中で寝て起きても成果が残るように細かく目標を変えたのが功を奏してこうして深夜に草稿を構想しております。 ちゃんとした道具を使おう GitHubのWebエディタ(?)で書くのは少しつらい。 普通、ローカルで書いてテストしたものをまとめて履歴に残す。そうしないとソースの変更とコメントから読み取れる意図を一致させにくい。 せっかく4段階に分けて開発したのに履歴からその歴史が読み取れない。 文字加工 区切られた数字 ⇒ 数値配列 (0は無視) filter(v=>v)は未定義やNaN、数値の0などを通さない(出典は失念)。parseIntが返すNaNを通さない。さらには0を通さないのが今回の要件ではマッチしたので楽だった。 カンマ区切りの数字を数値配列に変換 "1,2,3".split(',').map(c => parseInt(c, 10)).filter(v => v) //  [1, 2, 3] " 1 , AA2BB ,, 3,0,1 ".split(',').map(c => parseInt(c, 10)).filter(v => v) //  [1, 3, 1] 絵文字はsliceしづらい 2つのUnicodeで構成されているので、分断されかねない。 今回は想定する文字数が少なく、処理も軽いので一文字ずつ配列に入れて扱った。 虫をスライス "A?B".slice(1,2) // "\ud83d" おそらく?で表示される "A?B".slice(2,3) // "\udc1e" おそらく?で表示される "A?B".slice(1,3) // "?" misc 文字配列を文字列に ["a", "b"].join === "ab" 文字列を1文字ずつの配列に "ab".split("") 草稿をメモ代わりに使えば時短だし、Qiitaにアクセスできる様々な端末から閲覧できる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React appで作成したポートフォリオをGitHub Pagesでデプロイできた

React app(ポートフォリオサイト)をやっとデプロイできた 最終的に成功した時に参考にしたサイト 試した中でこのページ以外のやり方だと、なぜかエラーが出てデプロイできなかった。 エラーメッセージ npm ERR! missing script: build npm ERR! A complete log of this run can be found in: npm ERR! /Users/kakizakimanato/.npm/_logs/2021-06-07T14_05_58_985Z-debug.log npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! portfolio@0.1.0 deploy: `npm run build && gh-pages -d build` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the portfolio@0.1.0 deploy script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /Users/kakizakimanato/.npm/_logs/2021-06-07T14_05_59_032Z-debug.log kakizakimanato@kakiMacBook-Air portfolio % npm run deploy > portfolio@0.1.0 deploy /Users/kakizakimanato/deploy/portfolio > npm run build && gh-pages -d build npm ERR! missing script: build npm ERR! A complete log of this run can be found in: npm ERR! /Users/kakizakimanato/.npm/_logs/2021-06-07T14_06_57_636Z-debug.log npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! portfolio@0.1.0 deploy: `npm run build && gh-pages -d build` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the portfolio@0.1.0 deploy script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /Users/kakizakimanato/.npm/_logs/2021-06-07T14_06_57_690Z-debug.log まだ自分がデプロイできるかわからない時は、ファイルをコピーしてデプロイテスト用のディレクトリ内で試すといいかもしれません (色々な方法試しているうちにpackage.jsonファイルなどぐちゃぐちゃになります...) 少し追加でやらないといけないこと GitHubのアカウント情報を紐付ける $ git remote add origin https://github.com/<GitHubアカウント名>/<GitHubリポジトリ名>.git を実行する前に、GitHubアカウントの情報を設定する必要があった $ git config --global user.name "[githubユーザー名]" $ git config --global user.email "[githubで使用しているメールアドレス]" これでgit remote add originができる GitHub Pagesの設定 ソースブランチをmasterに設定し、rootファイルをdocsに変更し、["Save"]をクリック 数分待ってURLをクリックすると、成功していればWebサイトが見られるはず 次はファイルを編集後、再デプロイできるようになりたい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

InDesign スクリプト 属性を選択(構造の属性の値の検索結果から)

構造の属性の値の検索結果から属性を選択するスクリプトはこれで良いのかな・・・? /* 構造の属性の値の検索結果から属性を選択 更新 2021/06/09 */ // アプリ指定 #target "indesign"; // スクリプト名 var scriptName = "属性を選択(構造の属性の値の検索結果から)"; // 検索文字を入力 var findGrepText = prompt("検索する属性の値(JavaScriptの正規表現)\r(選択された構造内の属性がある場合はその中から検索)","",scriptName); // キャンセルされた時の処理 if(findGrepText == null){ // スクリプトを終了 exit(); } // エラーが発生した場合の処理 try{ // 正規表現オブジェクトを作り検索文字に入れる // mでマルチラインモード(^と$を各行の行頭、行末に一致させる為) findGrepText = new RegExp(findGrepText,"m"); // エラーの場合 }catch(e){ // 検索文字にnullを入れる findGrepText = null; } // 選択されているオブジェクト記憶用 var selectObjects = []; // 選択が存在しない場合 if(app.activeDocument.selection.length == 0){ // 構造内のすべての要素を選択する関数を使用 selectObjects = selectAllAttributes(app.activeDocument.xmlElements,selectObjects); // 選択が存在する場合 }else{ // 選択されているオブジェクト selectObjects = app.activeDocument.selection; // すべての選択を解除 app.activeDocument.selection = null; } // 選択オブジェクトの数だけ繰り返す for(var i = 0; i < selectObjects.length; i++){ // 選択オブジェクトが属性の場合 if(selectObjects[i].constructor.name == "XMLAttribute"){ // 属性名を検索して引っかかった場合 if(selectObjects[i].value.match(findGrepText)){ // 選択に追加 selectObjects[i].select(SelectionOptions.addTo); } } } // 結果表示 alert("選択数 " + app.activeDocument.selection.length,scriptName); /* 構造内の全ての属性を選択する為の関数、引数(xmlElements,再帰的処理の為の選択を記憶する配列) */ function selectAllAttributes(hierarchyElements,selectObjects){ // 要素の数だけ繰り返す for (var i = 0; i < hierarchyElements.length; i++) { // 要素に子要素が存在するか if(hierarchyElements[i].xmlElements.length > 0){ // 存在する場合再帰的処理 number = selectAllAttributes(hierarchyElements[i].xmlElements,selectObjects); } // 属性の数だけ繰り返す for (var ii = 0; ii < hierarchyElements[i].xmlAttributes.length; ii++) { // 要素を選択を記憶する為の配列に追加 selectObjects.push(hierarchyElements[i].xmlAttributes[ii]); } } // 選択する為のオブジェクトの値を戻す return selectObjects; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む