JQueryプラグインを使う
Jquery plugin
(function ($) { $.fn.hoge = function () { return $("p").click(function () { console.log("test!"); $(this).text("hello!"); }); }; })(jQuery);
これをjqueryとともにhtml側で読み込んでおく。
タイプスクリプトから読み込むには インターフェースを定義して、JQueryのメソッドに追加するファイルを用意しておく。
interface Hoge { hoge:() => JQuery<HTMLElement>; } interface JQuery extends Hoge { }
これで使える。
$("p").hoge();
使用例
html
<link rel="stylesheet" type="text/css" href="./jQuery.NumPad-master/jquery.numpad.css"> <script type="text/javascript" src="./jquery.min.js"></script> <script type="text/javascript" src="./jQuery.NumPad-master/jquery.numpad.js"></script> <script type="text/javascript" src="./usejq.js"> </script>
型定義 jQuert.Numpad.d.ts
interface NumPadPlugin { numpad:(option:{ textDone?:string, onChange?:(event:Event, value:string) => void }) => JQuery<HTMLElement>; } interface JQuery extends NumPadPlugin { }
呼び出し
$(".inputCell").numpad( { textDone:"Done?", onChange:(event, value) => { console.log(event); console.log(value); } } )
jquery等を使う。
Webアプリ環境
- npm パッケージマネージャ
- TypeScript 型付きのjavascrpt
- WebPack TypeScriptやHTMLのパーツ化のために使用
- Babel (今回使わなかった。) JSのバージョン吸収
npm
プロジェクトでパッケージ管理をスタートしたい場合
npm init
ではじめられる。 -yをつけておけば初期設定はすべてyesで飛ばせる。 これでpackage.jsonが作成される。
インストールしたいものを
npm install hoge
でインストールする。 インストールしたものはpackage.jsonに記録される。
- 本番環境と開発環境でインストールをわけれる。(開発環境の場合は--save-dev をつける等)
- globalにインストールしたい場合 -gをつける。
package.jsonの例
{ "name": "jsapp", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack", "watch": "webpack -w" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@types/dom-inputevent": "^1.0.1", "html-loader": "^0.5.5", "ts-loader": "^4.3.0", "typescript": "^2.8.3", "webpack": "^4.8.3", "webpack-cli": "^2.1.3" } }
scriptsのbuildにwebpackを設定しているので
npm run build
でwebpackを実行するとdistフォルダにコンパイルしたものが吐き出される。
- "@types/dom-inputevent" typesciptでdomのinputeventの型定義情報
- "html-loader" htmlをjsで読み込むのに使用
- "ts-loader" typescriptをjavascriptにコンパイルするのに使用
- "typescript" typescriptを使用する
- webpack, webpack-cli ts-loader, html-loader等を使うために使用
WebPack
設定はwebpack.config.js
インストール
npm install webpack webpack-cli --save-dev
実行
distフォルダ(設定で変更可能)に webpack.config.jsで設定しておいた処理を通してできたものが吐き出される。
実行はnpmのスクリプトに設定しておく
"scripts": { "build": "webpack" "watch": "webpack -w" }
設定
webpack.config.js
module.exports = { // or production mode: 'development', entry: { main:'./src/main.ts', menu:'./src/menu.ts'}, module: { rules: [ { test: /\.ts$/, use: 'ts-loader' }, { test: /\.html$/, loader: 'html-loader' } ] }, // for import resolve: { extensions: [ '.ts' ] } };
- entry ビルドを開始するエントリーポイントのjs
- output 出力
- module test:に指定された拡張子のものは use:に指定されたローダーで変換をかけること。
参考
html-loader
htmlをjsに読み込むために使用 設定はwebpack.config.jsの例を参照
使用例
let html = require('./hoge.html');
これでhtmlが文字列で取得できる。
TypeScript
インストール
npmで適宜インストール typescriptの他にwebpackで使用するために ts-loaderもインストールがいる。
設定ファイル
ルートにtsconfig.jsonをおく。
{ "compilerOptions": { "sourceMap": true, "target": "es5", "module": "es2015" // 出力モジュール名 } }
型名
必要に応じてtypescriptの型の定義情報をnpmでインストールする。
@types 型定義ファイル
例 @types/dom-inputevent
npm install --save @types/dom-inputevent
Jquery
typescript用に型情報@types/jquery をinstall。
html側でjqueryはimportしておくこと。
使用例
$("#listBox").mouseover(function() { $(this).fadeOut("slow"); });
Jquery plugin
(function ($) { $.fn.hoge = function () { return $("p").click(function () { console.log("test!"); $(this).text("hello!"); }); }; })(jQuery);
これをjqueryとともにhtml側で読み込んでおく。
タイプスクリプトから読み込むには インターフェースを定義して、JQueryのメソッドに追加するファイルを用意しておく。
interface Hoge { hoge:() => JQuery<HTMLElement>; } interface JQuery extends Hoge { }
これで使える。
$("p").hoge();
サンプル
Vue.jsのサンプルを打ち込んでみた。
簡単につかえるようだ。
<div> <div id="app-2"> <span v-bind:title="message"> Hover your mouse over me for a few seconds to see my dynamically bound title! </span> </div> <div id="app-3"> <span v-if="seen">Now you see me</span> </div> <div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div> <div id="app-5"> <p>{{ message2 }}</p> <button v-on:click="reverseMessage">Reverse Message</button> </div> <div id="app-6"> <p>{{ message }}</p> <input v-model="message"> </div> <div id="app-7"> <ol> <!-- Now we provide each todo-item with the todo object it's representing, so that its content can be dynamic. We also need to provide each component with a "key", which will be explained later. --> <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id"> </todo-item> </ol> </div> </div> <script src="./vue.js"></script> <script> var app2 = new Vue({ el: '#app-2', data: { message: 'You loaded this page on ' + new Date().toLocaleString() } }) var app3 = new Vue({ el: '#app-3', data: { seen: true } }) var app4 = new Vue({ el: '#app-4', data: { todos: [ { text: 'Learn JavaScript' }, { text: 'Learn Vue' }, { text: 'Build something awesome' } ] } }) var app5 = new Vue({ el: '#app-5', data: { message2: 'Hello Vue.js!' }, methods: { reverseMessage: function () { this.message2 = this.message2.split('').reverse().join('') } } }) var app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } }) Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) var app7 = new Vue({ el: '#app-7', data: { groceryList: [ { id: 0, text: 'Vegetables' }, { id: 1, text: 'Cheese' }, { id: 2, text: 'Whatever else humans are supposed to eat' } ] } }) </script>
html埋め込み
webpackのhtml-loaderを使ってhtmlをjavascriptで読み込んだ使う。
html-loaderのインストール。 npm install html-loader
webpack.config.jsを設定
module.exports = { entry: './app.js', output: { path: __dirname + "/dist", filename: "bundle.js"; }, module: { loaders: [ { test: /\.html$/, loader: 'html-loader' },//← これ ] }, };
jsでhtmlを読み込んで挿入する。
declare function require(x: string): any; let html = require('./keyboard.html'); let div = document.getElementById("keyboard") as HTMLDivElement; div.innerHTML = html;
感想
1. InputEventは型定義を読み込んだ。
npm install @types/dom-inputevent
2. 定義されてないものはinputEvent["inputType"]で取れた。
3. 定義していないプロパティも input["oldValue"] = input.value;で代入できた。
4. childNodesはArray.prototype.forEach.callを使う必要があった。
5. webpack.config.jsは複数entryは entry: {
main:'./src/main.ts',
menu:'./src/menu.ts'},みたいに指定すればできた。
6. ビルドする必要があるのは若干面倒かも。
typescript環境
TypeScript
インストール
typescript また、webpackで使用するために ts-loader もインストール
設定ファイル
ルートにtsconfig.json
{ "compilerOptions": { "sourceMap": true, "target": "es5", "module": "es2015" // 出力モジュール名 } }
webpackへの設定
webpack.config.jsを以下のように設定する
module.exports = { // or production mode: 'development', entry: './src/main.ts', module: { rules: [ { test: /\.ts$/, use: 'ts-loader' } ] }, // for import resolve: { extensions: [ '.ts' ] } };
ビルド
npm run build
webpackの使い方
WebPack
読み込んで使う。エントリーポイント
//spc/index.js import bar from './bar'; bar();
読み込まれる側
//src/bar.js export default function bar() { // }
これを設定するにはwebpack.config.jsを作る。
const path = require('path'); module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' } };
htmlで読み込む
<-- page.html --> <!doctype html> <html> <head> ... </head> <body> ... <script src="dist/main.js"></script> </body> </html>
変換する。
npx webpack
インストール
npm install webpack webpack-cli --save-dev
実行
npx webpack
distフォルダが作成され main.jsが作られる。これをhtmlで読み込む。
実行はnpmのスクリプトに設定しておく
"scripts": { "build": "webpack" "watch": "webpack -w" }
設定
webpack.config.js
module.exports = { entry: `./src/index.js`, output: { path: `${__dirname}/dist`, filename: 'main.js' }, module: { rules: { { test: /\.txt$/, use: 'hoge-loader' } } } };
- entry ビルドを開始するエントリーポイントのjs
- output 出力
- module test:に指定された拡張子のものは use:に指定されたローダーで変換をかけること。
技
基本
npm
パッケージ管理スタート
npm init これでpackage.jsonが作成される。
ローカルインストールは /node_modules 内にインストールされる。 -gをつけるとグローバルインストール。
アンインストールは uninstall
パッケージのアップデートは update
パッケージのリストは list
npm scripts
"scripts": { "キー": "シェル", "キー2": "シェル" }
キーの予約語
意味合い
- start
- restart
- stop
- test
これらは npm start等で実行できる。
フック
- publish npm publishの後
- install npm installの後
- uninstall npm uninstallの後
- update npm updateの後
予約されていないキーの実行
npm run-sctipt キー npm run キー
キーにプレフィックスつける
- pre
- post
フックのプレフィックス
- prepublish
- preinstall
- postuninstall
- preupdate
実行
- npm-run-all
- run-p A B 並列実行
- run-s A B 直列実行
コンフィグ設定
configフィールドに設定
"config": { "port": "8080" }
次のようにも設定できる
npm config set myapp:port 80
npm_package_config_portのように取り出せる。
DependenciesとdevDependencies
本番環境か開発環境か インストール時に-Dもしくは --save-devとするとPackageJSONにはdevDependenciesとして記録される。
uninstall時にpackega.jsonの本番環境から削除するなら--saveもしくは-S、開発環境から削除するなら--save-devもしくは -D
packege.jsonで一括インストール npm install
本番環境のみインストール npm install --production
validationらしきもの
とっかかりをつくってみた。
const toStr = (t) => { if (t == null) { return "null"; } else { return t.toString(); } } /** * * @param {Node} node * @returns {string} */ function nodeDesc(node) { const list = [node.nodeName, node.nodeType, node.nodeValue, node.hasChildNodes()]; const listStrings = list.map(x => toStr(x)); return listStrings.join(","); } /** * * @param {string} txt */ function log(txt) { console.log(txt); } /** * @param {Node} node * @returns {(txt:string) => void} */ var logNode = (node) => (txt) => log(txt + nodeDesc(node)); /** * * @param {Node} e * @returns {HTMLDivElement} */ const div = (e) => { if (e.nodeName == "DIV") { return e; } return null; }; /** * * @param {Node} e * @returns {HTMLElement} */ const htmlElement = (e) => { if (e instanceof HTMLElement) { return e; } return e; } /* nodes.find(x => x.nodeName == nodeName) */ /** * * @param {Node} node * @return {(Node) => Node} */ var findTag = (node) => (tagFunc) => (index) => { let t = node.firstChild; let count = 0; do { const x = tagFunc(t); if (x != null) { if (count == index) { return x; } count++; } t = t.nextSibling; } while (t != null); return null; } var findDiv = (node) => (index) => { return findTag(node)(div)(index); } /// IDを一括変更する /** * * @param {Node} node */ var cloneNode = (node) => (index) => { const dc = node.cloneNode(true); changeID(dc, index); return dc; }; /** * @param {Node} node * @param {number} index */ function changeID(node, index) { // console.log("node.id=",node.id); node.id = node.id +""+ index; // console.log(" => node.id=",node.id); for (let n of node.childNodes) { changeID(n,index); } } const id_cell = "cell"; const id_cell_title = "cell_title"; const id_cell_amount = "cell_amount"; const id_cell_icon = "cell_icon"; const id_listBox = "listBox"; const assertNonull = (o, msg) => { if (o!=null) { return true; } console.log("[Assert]"+msg); return false; } /** * @type{HTMLTableElement} */ const listBox = document.getElementById(id_listBox); console.log("listBox="+listBox); /** * @type{HTMLDivElement} */ const d = document.getElementById(id_cell); assertNonull(d,"id_cell is null"); console.log(id_cell+"="+d); for (let i = 0; i < 10; i++) { /// 複製 const dc = cloneNode(d)(i); dc.style.visibility = "visible"; /// listBox.appendChild(dc); /** * @type{HTMLImageElement} */ const icon = document.getElementById(id_cell_icon+i); icon.src = "menu/icon_" + ('00'+i).slice(-2) + ".png"; const title = document.getElementById(id_cell_title+i); if (title instanceof HTMLDivElement) { title.innerText = "hoge" + i; } const amount = document.getElementById(id_cell_amount+i); if (amount instanceof HTMLInputElement) { amount.value = "" + i; amount.innerText = "" + (i * 100) + "Yen"; amount.oninput = (txt) => { if (txt instanceof InputEvent) { if (txt.inputType == "deleteContentBackward") { console.log("delete...."); amount.oldValue = amount.value; } else { console.log(amount.value + "=>+" + txt.data); const reg = /^\d{0,6}$/; if (amount.value.match(reg) != null) { console.log("ok"); amount.oldValue = amount.value; } else { console.log("invalid"); console.log(txt); const pos = amount.selectionStart; amount.value = amount.oldValue; amount.selectionStart = pos-1; amount.selectionEnd = pos-1; // amount.value = amount.value.slice(0,-1); } } } } } // const found = findDiv(dc)(1); // if (found != null) { // found.innerText = "hoge!"; // } }
クラスで指定できるようにした。
const toStr = (t) => { if (t == null) { return "null"; } else { return t.toString(); } } /** * * @param {Node} node * @returns {string} */ function nodeDesc(node) { const list = [node.nodeName, node.nodeType, node.nodeValue, node.hasChildNodes()]; const listStrings = list.map(x => toStr(x)); return listStrings.join(","); } /** * * @param {string} txt */ function log(txt) { console.log(txt); } /** * @param {Node} node * @returns {(txt:string) => void} */ var logNode = (node) => (txt) => log(txt + nodeDesc(node)); /** * * @param {Node} e * @returns {HTMLDivElement} */ const div = (e) => { if (e.nodeName == "DIV") { return e; } return null; }; /** * * @param {Node} e * @returns {HTMLElement} */ const htmlElement = (e) => { if (e instanceof HTMLElement) { return e; } return e; } /* nodes.find(x => x.nodeName == nodeName) */ /** * * @param {Node} node * @return {(Node) => Node} */ var findTag = (node) => (tagFunc) => (index) => { let t = node.firstChild; let count = 0; do { const x = tagFunc(t); if (x != null) { if (count == index) { return x; } count++; } t = t.nextSibling; } while (t != null); return null; } var findDiv = (node) => (index) => { return findTag(node)(div)(index); } /// IDを一括変更する /** * * @param {Node} node */ var cloneNode = (node) => (index) => { const dc = node.cloneNode(true); changeID(dc, index); return dc; }; /** * @param {Node} node * @param {number} index */ function changeID(node, index) { // console.log("node.id=",node.id); node.id = node.id +""+ index; // console.log(" => node.id=",node.id); for (let n of node.childNodes) { changeID(n,index); } } const id_cell = "cell"; const id_cell_title = "cell_title"; const id_cell_amount = "cell_amount"; const id_cell_icon = "cell_icon"; const id_listBox = "listBox"; const assertNonull = (o, msg) => { if (o!=null) { return true; } console.log("[Assert]"+msg); return false; } /** * @type{HTMLTableElement} */ const listBox = document.getElementById(id_listBox); console.log("listBox="+listBox); /** * * @param {HTMLInputElement} input * @returns {(inputEvent:Event) => void} */ const amountValidation = (input) => (inputEvent) => { if (inputEvent instanceof InputEvent) { if (inputEvent.inputType == "deleteContentBackward") { console.log("delete...."); input.oldValue = input.value; } else { console.log(input.value + "=>+" + inputEvent.data); const reg = /^\d{0,6}$/; if (input.value.match(reg) != null) { console.log("ok"); input.oldValue = input.value; } else { console.log("invalid"); console.log(inputEvent); const pos = input.selectionStart; input.value = input.oldValue; input.selectionStart = pos-1; input.selectionEnd = pos-1; // amount.value = amount.value.slice(0,-1); } } } } /** * @type{HTMLDivElement} */ const d = document.getElementById(id_cell); assertNonull(d,"id_cell is null"); console.log(id_cell+"="+d); for (let i = 0; i < 10; i++) { /// 複製 const dc = cloneNode(d)(i); dc.style.visibility = "visible"; /// listBox.appendChild(dc); /** * @type{HTMLImageElement} */ const icon = document.getElementById(id_cell_icon+i); icon.src = "menu/icon_" + ('00'+i).slice(-2) + ".png"; const title = document.getElementById(id_cell_title+i); if (title instanceof HTMLDivElement) { title.innerText = "hoge" + i; } // const found = findDiv(dc)(1); // if (found != null) { // found.innerText = "hoge!"; // } } // setValidation const className_validation_amount = "validation_amount"; const ls = document.getElementsByClassName(className_validation_amount); console.log("valid ls" + ls.length); for (const l of ls) { console.log(l); if (l instanceof HTMLInputElement) { console.log(l); l.oldValue = l.value; let v = amountValidation(l); l.oninput = v; } }
関数に出した。コメントで型が定義できるらしい。
const toStr = (t) => { if (t == null) { return "null"; } else { return t.toString(); } } /** * * @param {Node} node * @returns {string} */ function nodeDesc(node) { const list = [node.nodeName, node.nodeType, node.nodeValue, node.hasChildNodes()]; const listStrings = list.map(x => toStr(x)); return listStrings.join(","); } /** * * @param {string} txt */ function log(txt) { console.log(txt); } /** * @param {Node} node * @returns {(txt:string) => void} */ var logNode = (node) => (txt) => log(txt + nodeDesc(node)); /** * * @param {Node} e * @returns {HTMLDivElement} */ const div = (e) => { if (e.nodeName == "DIV") { return e; } return null; }; /** * * @param {Node} e * @returns {HTMLElement} */ const htmlElement = (e) => { if (e instanceof HTMLElement) { return e; } return e; } /* nodes.find(x => x.nodeName == nodeName) */ /** * * @param {Node} node * @return {(Node) => Node} */ var findTag = (node) => (tagFunc) => (index) => { let t = node.firstChild; let count = 0; do { const x = tagFunc(t); if (x != null) { if (count == index) { return x; } count++; } t = t.nextSibling; } while (t != null); return null; } var findDiv = (node) => (index) => { return findTag(node)(div)(index); } /// IDを一括変更する /** * * @param {Node} node */ var cloneNode = (node) => (index) => { const dc = node.cloneNode(true); changeID(dc, index); return dc; }; /** * @param {Node} node * @param {number} index */ function changeID(node, index) { // console.log("node.id=",node.id); node.id = node.id +""+ index; // console.log(" => node.id=",node.id); for (let n of node.childNodes) { changeID(n,index); } } const id_cell = "cell"; const id_cell_title = "cell_title"; const id_cell_amount = "cell_amount"; const id_cell_icon = "cell_icon"; const id_listBox = "listBox"; const assertNonull = (o, msg) => { if (o!=null) { return true; } console.log("[Assert]"+msg); return false; } /** * @type{HTMLTableElement} */ const listBox = document.getElementById(id_listBox); console.log("listBox="+listBox); /** * * @typedef {(txt:String)=>boolean} Rule * @param {String} txt * @returns {boolean} */ const numberRule6 = (txt) => { const reg = /^\d{0,6}$/; if (txt.match(reg) != null) { return true; } return false; } /** * * @param {HTMLInputElement} input * @returns {(rule:Rule) => (inputEvent:Event) => void} */ const amountValidation = (input) => (rule) => (inputEvent) => { console.log("amountValidation"); if (inputEvent instanceof InputEvent) { if (inputEvent.inputType == "deleteContentBackward") { console.log("delete...."); input.oldValue = input.value; } else { console.log(input.value + "=>+" + inputEvent.data); if (rule(input.value)) { console.log("ok"); input.oldValue = input.value; } else { console.log("invalid"); console.log(inputEvent); const pos = input.selectionStart; input.value = input.oldValue; input.selectionStart = pos-1; input.selectionEnd = pos-1; // amount.value = amount.value.slice(0,-1); } } } } /** * @type{HTMLDivElement} */ const d = document.getElementById(id_cell); assertNonull(d,"id_cell is null"); console.log(id_cell+"="+d); for (let i = 0; i < 10; i++) { /// 複製 const dc = cloneNode(d)(i); dc.style.visibility = "visible"; /// listBox.appendChild(dc); /** * @type{HTMLImageElement} */ const icon = document.getElementById(id_cell_icon+i); icon.src = "menu/icon_" + ('00'+i).slice(-2) + ".png"; const title = document.getElementById(id_cell_title+i); if (title instanceof HTMLDivElement) { title.innerText = "hoge" + i; } // const found = findDiv(dc)(1); // if (found != null) { // found.innerText = "hoge!"; // } } // setValidation const className_validation_amount = "validation_amount"; const ls = document.getElementsByClassName(className_validation_amount); console.log("valid ls" + ls.length); for (const l of ls) { console.log(l); if (l instanceof HTMLInputElement) { console.log(l); l.oldValue = l.value; let v = amountValidation(l)(numberRule6); l.oninput = v; } }
レイアウト作成続
flexを使うほうが調整が簡単なことがわかった。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>List</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <link rel="stylesheet" type="text/css" href="style.css"> <script type="text/javascript" src="jquery.min.js"></script> <style type="text/css"> .container { text-align: center; } .listBox { display: flex; flex-direction: column; align-items: center; } .cell { width: 330px; height: 70px; } .cell_icon { flex-basis: 80px; flex-grow: 0; } .cell_title { flex-basis: auto; flex-grow: 1; text-align: left; padding-left: 20px; } .cell_amount { flex-basis: auto; flex-grow: 0; text-align: right; padding-right: 10px; } .cellBox { width: 320px; height: 66px; background: linear-gradient(#EEEEEE, #FFFFFF); display: flex; flex-direction: row; justify-content: space-between; align-content: center; align-items: center; border: #000000; border-width: 1px; border-radius:5px; border-style:solid; } body { background: linear-gradient(#0000CC, #0000FF); width: 800px; height: 800px; } </style> </head> <body> <div id="container" class="container"> <div id="cell" class="cell" style="visibility:hidden;"> <div id="cellBox" class="cellBox"> <div class="cell_icon"><img id="cell_icon" src="menu/icon_01.png"></div> <div class="cell_title" id="cell_title">hoge</div> <div class="cell_amount" id="cell_amount"></div> </div> </div> <div id="listBox" class="listBox"></div> </div> </body> <script type="text/javascript" src="menu.js"> </script> </html>
テーブル
書いてみたが使わなくて良いみたい。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>List</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <link rel="stylesheet" type="text/css" href="style.css"> <script type="text/javascript" src="jquery.min.js"></script> <style type="text/css"> .listBox { } .cell { width: 320px; height: 66px; background: linear-gradient(#EEEEEE, #FFFFFF); /* border: #000000; */ /* border-width: 1px; */ display: flex; flex-direction: row; align-content: center; align-items: center; /* border-radius:5px; */ /* border-style:solid; */ } body { background: linear-gradient(#0000CC, #0000FF); width: 400px; height: 800px; } </style> </head> <body> <div id="container"> <table> <tr id="cell" class="cell" style="visibility:hidden;"> <td><img id="cell_icon" src="menu/icon_01.png"></td> <td id="cell_title">hoge</td> <td id="cell_amount"></td> </tr> </table> <table id="listBox" class="listBox"></table> </div> </body> <script type="text/javascript" src="menu.js"> </script> </html>
書いてみた
まだぐしゃぐしゃだがやはりスタイルはまとめて他の場所に書くほうがすっきりするようだ。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>List</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <link rel="stylesheet" type="text/css" href="style.css"> <script type="text/javascript" src="jquery.min.js"></script> <style type="text/css"> .cell { width: 320px; height: 66px; background: white; border: black; display: flex; flex-direction: row; align-content: center; align-items: center; border-radius:10px; } body { background: linear-gradient(#0000CC, #0000FF); width: 400px; height: 800px; } </style> </head> <body> <div id="container"> <div id="cell" class="cell" style="visibility:hidden;"> <img id="cell_icon" src="menu/icon_01.png"> <div id="cell_title">hoge</div> <div id="cell_amount"></div> </div> <div id="listBox"></div> </div> </body> <script type="text/javascript" src="menu.js"> </script> </html>
関数とコメント2
更に色々書いてみた。
/** * @type{HTMLDivElement} */ const listBox = document.getElementById("listBox"); const toStr = (t) => { if (t == null) { return "null"; } else { return t.toString(); } } /** * * @param {Node} node * @returns {string} */ function nodeDesc(node) { const list = [node.nodeName, node.nodeType, node.nodeValue, node.hasChildNodes()]; const listStrings = list.map(x => toStr(x)); return listStrings.join(","); } /** * * @param {string} txt */ function log(txt) { console.log(txt); } /** * @param {Node} node * @returns {(txt:string) => void} */ var logNode = (node) => (txt) => log(txt + nodeDesc(node)); /** * * @param {Node} e * @returns {HTMLDivElement} */ const div = (e) => { if (e.nodeName == "DIV") { return e; } return null; }; /* nodes.find(x => x.nodeName == nodeName) */ /** * * @param {Node} node * @return {(Node) => Node} */ var findTag = (node) => (tagFunc) => (index) => { let t = node.firstChild; let count = 0; do { const x = tagFunc(t); if (x != null) { if (count == index) { return x; } count++; } t = t.nextSibling; } while (t != null); return null; } var findDiv = (node) => (index) => { return findTag(node)(div)(index); } /// IDを一括変更する var cloneNode = (node) => (index) => { const dc = d.cloneNode(true); changeID(dc, index); return dc; }; /** * @param {Node} node * @param {number} index */ function changeID(node, index) { // console.log("node.id=",node.id); node.id = node.id +""+ index; // console.log(" => node.id=",node.id); for (let n of node.childNodes) { changeID(n,index); } } const id_cell = "cell"; const id_cell_title = "cell_title"; const id_cell_amount = "cell_amount"; const id_cell_icon = "cell_icon"; /** * @type{HTMLDivElement} */ const d = document.getElementById(id_cell); /** * @type{HTMLDivElement} */ for (let i = 0; i < 10; i++) { /// 複製 const dc = cloneNode(d)(i); dc.style.visibility = "visible"; /// listBox.appendChild(dc); /** * @type{HTMLImageElement} */ const icon = document.getElementById(id_cell_icon+i); icon.src = "menu/icon_" + ('00'+i).slice(-2) + ".png"; const title = document.getElementById(id_cell_title+i); title.innerText = "hoge" + i; const amount = document.getElementById(id_cell_amount+i); amount.innerText = "" + (i * 100) + "Yen"; // const found = findDiv(dc)(1); // if (found != null) { // found.innerText = "hoge!"; // } }