実現したいこと
・GAS経由の自作サイトにハイパーリンクを表示
前提
会社の業務改善として、スプレッドシートの内容をサイト形式で検索できるように作り上げている最中です。
サイトの作成については、色々調べてある程度形にはなりました。
ただその中で、表示元のスプレッドシートにあるリンクが自作サイトで開けるようにならず、苦戦をしております。
おそらくHTML側にコードを追加する必要があるとは感じているのですが、どこに何をいれればいいのかがわかりません。
発生している問題・エラーメッセージ
・リンクが文字でクリックができない
(今回やりたいのは、住所のハイパーリンクを開けるようにしたい)
参考のシートはサンプルのためリンクは一か所のみ、本番用にはハイパーリンクが全て入っている状態です。
該当のソースコード
・自作サイト(ここの住所部分をハイパーリンクとして扱いたい)
https://script.google.com/macros/s/AKfycbyxbutqGP7eQVl8iXorTNKllOmA7z2IKKz6UI9NMf9cjPgBDacw2lIn0F-9ckIn/exec
<!DOCTYPE html> <html style="overflow-y:hidden"> <head> <base target="_top"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <style> ::-webkit-scrollbar { background: transparent; height: 10px; width: 8px; } ::-webkit-scrollbar-thumb { border: none; background: #bbb; -webkit-border-radius: 8px; border-radius: 8px; min-height: 40px; } thead th { position: -webkit-sticky; position: sticky; top: -1px; background-color: #ddd; } .btn { position: fixed; width: 50px; height: 50px; color: white; border-radius: 50px; display: flex; justify-content: center; align-items: center; opacity: 0.4; box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); transition: 200ms; user-select: none; } .btn:hover { opacity: 0.9; } .btn:active { opacity: 1; } </style> </head> <body> <div id="app"> <div style="display: flex;"> <!-- フィルタエリア --> <div style=" width: 300px; height: 100vh; background-color: #fafafa; padding: 0 30px; overflow: auto; "> <!-- タイトル --> <h1 class="title is-4" style="margin-top: 50px;"> <span class="material-icons">filter_list</span> フィルタ </h1> <!-- フォーム --> <template v-for="(key, index) in keys"> <div v-if="!isHidden(key)" style="margin-bottom: 1em;"> <!-- 項目名 --> <label class="label is-small">{{ key.replace(/:.*$/,"") }}</label> <!-- プルダウン(:select["A","B"...] が項目名末尾に付与されていた場合) --> <template v-if="isSelect(key)"> <select v-model="conditions[index]" class="select is-small"> <option value="">選択なし</option> <option v-for="option in getOptions(key)" :value="option">{{ option }}</option> </select> </template> <!-- ラジオボタン(:radio["A","B"...] が項目名末尾に付与されていた場合) --> <template v-else-if="isRadio(key)"> <label for="radio-none"> <input type="radio" id="radio-none" value="" v-model="conditions[index]" /> 選択なし </label> <label v-for="(option, radioIndex) in getOptions(key)" :for="'radio-' + radioIndex"> <input type="radio" :id="'radio-' + radioIndex" :value="option" v-model="conditions[index]" /> {{ option }} </label> </template> <!-- チェックボックス(:checkbox["A","B"...] が項目名末尾に付与されていた場合) --> <template v-else-if="isCheckbox(key)"> <label v-for="(option, checkboxIndex) in getOptions(key)" :for="'checkbox-' + checkboxIndex"> <input type="checkbox" :id="'checkbox-' + checkboxIndex" :value="option" v-model="conditions[index]" /> {{ option }} </label> </template> <!-- テキストボックス(指定なしの場合) --> <input v-else v-model="conditions[index]" type="text" class="input is-small"> </div> </template> <!-- フィルタクリアボタン --> <div @click="initConditions()" class="btn" style="bottom: 30px; left: 220px; background-color: #e85a5a;" > <span class="material-icons">clear</span> </div> </div> <!-- データエリア --> <div style=" max-width: calc(100% - 300px); height: 100vh; padding: 0 50px; overflow: auto; "> <!-- タイトル --> <h1 class="title is-4" style="margin-top: 50px;"> <span class="material-icons">description</span> <?= title ?> </h1> <!-- テーブル --> <table class="table is-striped is-hoverable" style="white-space: nowrap; position: relative;"> <thead> <tr> <th v-for="key in keys">{{ key.replace(/:.*$/,"") }}</th> </tr> </thead> <tbody> <template v-for="record in records"> <tr v-if="checkCondition(record)"> <td v-for="item in record">{{ item }}</td> </tr> </template> </tbody> </table> <!-- ダウンロードボタン --> <div @click="downloadCSV()" class="btn" style="bottom: 30px; right: 30px; background-color: #3a93e8;" > <span class="material-icons">file_download</span> </div> </div> </div> </div> <!-- Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script> <script> var app = new Vue({ el: '#app', data: { keys: [], // シートの1行目 records: [], // シートの2行目以降 conditions: [], // 入力した絞込条件 }, mounted: function(){ google.script.run.withSuccessHandler(function(text) { const response = JSON.parse(text) app.keys = response[0]; app.records = response.slice(1); app.records.splice(); app.initConditions(); }).getSheetData(); }, methods: { // フィルタ条件を初期化する initConditions: function(){ this.conditions = app.keys.map((key) => { return app.isCheckbox(key) ? [] : "" }) }, // レコードが全ての絞込条件に合致するかチェックする checkCondition: function(record){ for (let i = 0; i < this.keys.length; i++){ if ( this.isCheckbox(this.keys[i]) ){ if (this.conditions[i].length && !this.conditions[i].includes(record[i])) return false; } else { if ( this.conditions[i] && !record[i].includes(this.conditions[i])) return false; } } return true; }, // CSVファイルをダウンロードする downloadCSV: function(){ const filename = "data.csv"; let data = '\"' + this.keys.join('\",\"') + '\"\r\n'; for (const record of this.records){ if ( this.checkCondition(record) ){ data += '\"' + record.join('\",\"') + '\"\r\n'; } } const bom = new Uint8Array([0xef, 0xbb, 0xbf]); const blob = new Blob([bom, data], { type: "text/csv" }); const url = (window.URL || window.webkitURL).createObjectURL(blob); const download = document.createElement("a"); download.href = url; download.download = filename; download.click(); (window.URL || window.webkitURL).revokeObjectURL(url); }, // フォームタイプをチェックする isHidden: function(key){ return /^.*:hidden/.test(key) }, isSelect: function(key){ return /^.*:select\[.*\]$/.test(key) }, isRadio: function(key){ return /^.*:radio\[.*\]$/.test(key) }, isCheckbox: function(key){ return /^.*:checkbox\[.*\]$/.test(key) }, // シートの項目名末尾に付与した選択肢の配列を返す getOptions: function(key){ const param = /:(select|radio|checkbox)\[.*\]$/.exec(key) // param[0] => ':select["A","B","C"]' const optionsString = /\[.*\]/.exec(param[0]) // optionsString[0] => '["A","B","C"]' return JSON.parse(optionsString[0]) // return => ["A","B","C"] } } }) </script> </body> </html>
補足情報(FW/ツールのバージョンなど)
全くの素人のため、専門用語等はほとんどわかりません。
見よう見まねで色々引っ張ってきて使用している状況です。
あなたの回答
tips
プレビュー