質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

3310閲覧

各ボタンから追加した各テキストエリアをlocalStorageで保存・削除を実行したい

suisuin

総合スコア17

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2017/01/17 10:50

###各ボタンから追加した各テキストエリアをlocalStorageで保存・削除を実行したい

ワードプレスでページ製作をしています。javaに関しては素人で検索した素材をよく利用しています。

今回、複数のテキストエリア生成ボタンを用意し、追加した要素&テキストエリアの内容を保存するために検索しヒットした情報を実行、微調整、繋ぎ合わせと素人ならではで試行錯誤しております。

localStorageを利用して次のことを実現したいです。
(1)appendで追加した<li><texterea><button>~をブラウザの更新時に消えないように保存する
(2)appendで追加した各テキストエリアの内容を(各々or一括)保存する
(3)appendで追加した<li>を削除する
(4)各テキストエリアで保存した内容を全てクリアにする
現状、追加は出来ても要素&テキストエリアの保存・削除ができません。

ただいま検証しているコードが下記になります。

###各ボタンでテキストエリアを追加するコード

<button id="ma">button1</button> <button id="sa">button2</button> <button id="ka">button3</button> <ul id="list"> </ul> </li> </ul> <script> $(function() { $("#ma").click(function() { $("#list").append('<textarea id="text1" class="text1"></textarea><button id="save1">保存</button><button id="delete1" onClick="history.go(0)">削除</button>'); }); $("#sa").click(function() { $("#list").append('<textarea id="text2" class="text2"></textarea><button id="save2">保存</button><button id="delete2" onClick="history.go(0)">削除</button>'); }); $("#ka").click(function() { $("#list").append('<textarea id="text3" class="text3"></textarea><button id="save3">保存</button><button id="delete3" onClick="history.go(0)">削除</button>'); //とりあえず3個ですが実際はは10個以上作る予定です。 }); }); <script>

上記のコードをもとに、localStorageの指示をあてはめようと苦戦しています。

###追加された要素&テキストエリアをlocalStorageで保存・削除

以下、複数のテキストのエリアの保存ができたスクリプトです。
これをうまく上記のスクリプトに組み合わせられれば良いのですが、そもそも見当違いかもしれません。

$(function(){ $("#list .text1").val(window.localStorage.getItem("text1")); $("#list .text2").val(window.localStorage.getItem("text2")); $("#list .text3").val(window.localStorage.getItem("text3")); }); $("#save1").click(function(){ window.localStorage.setItem('text1', $("#list .text1").val()); alert("データ1を保存しました。"); }); $("#save2").click(function(){ window.localStorage.setItem('text2', $("#list .text2").val()); alert("データ2を保存しました。"); }); $("#save3").click(function(){ window.localStorage.setItem('text3', $("#list .text3").val()); alert("データ3を保存しました。"); }); $("#delete").click(function(){ window.localStorage.clear(); $("#textarea1").val(''); $("#textarea2").val(''); $("#textarea3").val(''); alert("データを全て削除しました。"); }); $("#delete1").click(function(){ window.localStorage.removeItem('text1', $("list").val()); alert("データ1を削除しました。"); }); $("#delete2").click(function(){ window.localStorage.removeItem('text2', $("#list").val()); alert("データ1を削除しました。"); }); $("#delete3").click(function(){ window.localStorage.removeItem('text3', $("#list").val()); alert("データ3を削除しました。"); });

localStorageは文字列の保存ができないため、HTMLなどはオブジェクトに変換し保存ということでいろいろコードを当てはめたのですが保存できず。なのでHTMLは置いといて各ボタンからテキストエリアのみを追加、さらにテキストエリアの内容の保存を試みたりしたのですがうまくいきません。

どうかご教授くださいますようよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

まず初めに、これはlocalStorageに保存ができないのではなく
クリックイベントが付与できていないのが原因です。

#save(n)に対するclickイベントがdocument.readyのタイミングで定義されていますが
#save(n)はbuttonをクリックした際に追加される要素です。つまり、document.readyの段階ではページ上に存在していない要素です。
そのため、例え.on('click', fun)で定義しようと、そのイベントは付与されません。(alertが実行されないのはその為です)
正しくは、append()したタイミングで.on('click', fun)を行う必要があります。

JavaScript

1//Ex. 2$("#list").append('<textarea id="text1" class="text1"></textarea><button id="save1">保存</button><button id="delete1" onClick="history.go(0)">削除</button>'); 3$('#save1').on('click', function(){ 4 //クリック時の処理 5}); 6

とはいえ、この要素ごとにいちいち一つづつイベントを作成、付与していくのはあまりにも冗長かつ
無駄にメモリを使用するので、親要素でイベント管理するほうが良いかなと思います。

そこで、まずはHtmlから少し改善して

Html

1<!--各ボタンに対して共通クラスを付与。(ここでは.butoon)--> 2<button id="ma" class="button">button1</button> 3<button id="sa" class="button">button2</button> 4<button id="ka" class="button">button3</button> 5 <ul id="list"> 6 </ul>

JavaScript

1//コード内でconst,letを使用していますが、そのままvarに置き換えてもOKです。 2$(function() { 3 const wrapper = $('#list'); 4 //documentではなく、上記Htmlの親要素のidでもOK 5 $(document).on('click', '.button, .save, .delete', function(){ //$(element)以下の.button, .save, .deleteを持つ要素すべてに対してクリックイベントを(この方法は後から追加された要素に対しても有効) 6 let elClass = $(this).attr('class') //クリックされた要素のクラス名を取得 7 let num = $('.'+elClass).index(this); //その要素が同一クラスを持つ要素の中で何番目か取得 8 let n = num + 1; 9 10 if( $(this).hasClass('button') ){ //.buttonなら 11 wrapper.append('<textarea id="text'+ n +'" class="text"></textarea><button id="save'+ n +'" class="save">保存</button><button id="delete'+ n +'" class="delete" onClick="history.go(0)">削除</button>'); //追加されるtextarea、保存、削除用ボタンも共通クラスに変更 12 }else if( $(this).hasClass('save') ){ //.saveなら 13 let val = $("#list .text").eq(num).val(); 14 localStorage.setItem('text'+n , val ); //window.は無くてOK 15 alert("データ"+n+"を保存しました。"); 16 }else{ //.deleteなら 17 localStorage.removeItem('text'+n); // removeItem()の引数はkeyのみ(valueは不要) 18 alert("データ"+n+"を削除しました。"); 19 } 20 }); 21});

getItem()の箇所と
localStorage.clear()の箇所はいまいちどのようにしたいのかピンとこなかったので割愛しています。

buttonを押した時に追加されるtextarea内に、localStorage内に対応するデータが保存されていた場合
その内容を表示する、というのであれば上記コード内のif( $(this).hasClass('button') ){ ...}の箇所へ

wrapper.append('<textarea〜); if(localStorage.getItem('text'+n)){ $('#text'+n).val(localStorage.getItem('text'+n)) }

とでもしてやれば良いでしょう。

削除ボタンに対してhistory.go(0)がonClick属性で付与されているため、
削除ボタンを押すと毎回リロードされてしまうかたちになりますが、これも意図通りなのでしょうか?

また、#deleteという要素が質問のコード内に存在していないため
その要素へ設定したクリックイベントも割愛しています。


localStorageは文字列の保存ができないため

そんなことはありません。localStorageは文字列で保存されます。
(もしくはオブジェクト形式での保存のいずれかになります)

あと細かいことですが、JavaとJavaScriptは別言語ですので混同しないようにしておきましょう。

####追記
イメージ説明
こちらの環境ではすべて保存ができていますが…。(リアルタイムでstorageへ追加されているのが確認できない場合あり。注:保存はされている=リロードすると保存できているのが確認可)

投稿2017/01/17 19:09

編集2017/01/19 12:56
manabufukai

総合スコア700

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suisuin

2017/01/19 12:15

分かりやすい解説並びに時間をかけてくださりありがとうございます。 ご指摘の「localStorageは文字列の保存ができない」件は私の書き間違えでした。javaの件も確認し違いを理解しました。知らないままだと恥ですね、失礼しました。 また、削除ボタンにあるhistory.go(0)がonClick属性で付与については、サイトから一部拝借し作り変えていくうちにその意味を失っておりました。不要のコードになります。 この程度の認識で恐縮ですが、トライした結果 「append()したタイミングで~」でのコードにてうまくいきました! しかし、ご指摘にあった無駄にメモリを使用するというのであれば確かにいただけません。 、 ①HtmlとJavaScriptのコードをそのまま試しましたがテキストエリアに内容が保存できませんでした。 ②次に「if( $(this).hasClass('button') ){ ...}の箇所へ」のコードを追記しました、 結果、三つのボタンそれぞれに保存されず、buttonのクラスに対し保存されているせいか、1つのテキストエリア内で上書き保存される状態でした。 ③また、「//documentではなく、上記Htmlの親要素のidでもOK」では、 「$(document)」⇒「$(#ma)」や「$('#ma')」や「$("#ma")」と変えてみましたが、結果テキストエリア枠自体が表示されませんでした。 解説を何度も読み返しては検索で調べ、やっつけで手当たり次第いじってみたのですがだめでした。 ただその中でも、「親要素でイベント管理」の観点から検索した中に気になる情報がありました。 http://blog.sarabande.jp/post/26407900803 上記URLはほぼ理想の形だったのですが、textareaでなくinputで組まれておりました。試行錯誤、修正してみたのですがこれもtextareaで保存できず断念しました。 ただ、私の質問時に記載したコードは繋ぎ合わせでしたので、上記でURLからであればinputをtextareaに変えて正常に動けば解決としたいのですが、どうか、引き続きお力添えいただけないでしょうか。
manabufukai

2017/01/19 13:09 編集

まんまの内容でこちらの環境では保存→出力ができていますが…?(基本コードは検証済みのものを記載しています) 一応、キャプチャを回答文にも追記しました。 ②が起こる時点でどこかの記述が違っている可能性があります。 あるいは、他のパートの要素に同一のクラスが使用されていないかも合わせてチェックしてみてください。 ※内部処理的にそれぞれの保存ボタン、削除ボタンに番号を振って重複しないようにしてあるのが回答のコードです。 また、保存はsaveクラスを持つ要素=保存ボタンによって行っています。.buttonではありません。 ③「親要素」というのは回答文のhtmlの箇所を包み込んでいるhtml要素を指します。つまるところ <div id="foo"> <button id="ma" class="button">button1</button> <button id="sa" class="button">button2</button> <button id="ka" class="button">button3</button> <ul id="list"> </ul> </div> などとなっている場合、この#fooが親要素となり、#maはbuttonのidなので親要素ではありません。
suisuin

2017/01/21 10:33

次のことでようやく成功しました。 1. .buttonを変更 2.提示頂いたjavascriptの6行目、データが保存時のコードの4行目にセミコロンを入れる。 3. if( $(this).hasClass('button') ){ ...}の箇所へ「 localStorage.setItem("list", $("#list").html());」を追記 3は、片っ端から当てはめてみて試した結果です。ただ、意味はよく理解できてませんが 何においても解決できました。ありがとうございました。
manabufukai

2017/01/21 11:05

ええと… if( $(this).hasClass('button') ){ ...}の箇所へlocalStorageへの保存処理を入れると 回答文画像で言う所の「button1,2,3」をクリックした時にtextarea内の内容が保存されるようになります。 「保存」ボタンをクリックした時にtextarea内の内容がlocalStorageへ保存されるようにしたいのではないのですか? 「button1,2,3」をクリックした時に、へ仕様を変更されたのであればそれでいいのではないでしょうか。 また、「 localStorage.setItem("list", $("#list").html());」では textareaを含むhtml要素(<textarea id="text(n)" class="text" /><button>...)といった内容をlocalStorageへ保存するということになるのでは? またkey名が重複しているのでどのボタンをクリックしても内容を上書きするということになるかと。 それでうまく行っているのであれば、提示していただいている内容と実際の環境に差異があるか、こちらが質問の内容を勘違いをしているかかなと思います。
suisuin

2017/01/22 09:25

すみません。先に指摘の 勝手に追記した「localStorage.setItem("list", $("#list").html());」を削除した上で、各ボタンそれぞれの保存を確認できました。 ただその前まで出来ていなかったことで、恐らくそれまで色々試していたコードが何か残っていて悪さをしていたのではと思います。 目的については、仰るとおりです。textarea内の内容がlocalStorageへ保存したかったのですが、回答をいただき動作を確認していくうちに 「リロードしてもwrapper.appendで追加された内容表示を残せないか」と思い色々試してました。これも原因に含まれると思います。 現状、ボタンをクリックしテキストエリアを追加 ⇒ 保存ボタンでテキストエリアの内容が保存 ⇒ リロードしたのちボタンをクリックすればテキストエリアの保存内容が確認できます。これをリロードしてもテキストエリアの表示を残したいと思いました。ただ当初の質問とは異なるのではと思いそこは触れずにいた次第です。 そこは自分で何とかできないかなと思い今挑戦しています。
guest

0

JavaScipt

1 2$(document).on('click', '#save1', function(){ 3 window.localStorage.setItem('text1', $("#list .text1").val()); 4 alert("データ1を保存しました。"); 5}); 6 7$(document).on('click', '#save2', function(){ 8 window.localStorage.setItem('text2', $("#list .text2").val()); 9 alert("データ2を保存しました。"); 10}); 11 12$(document).on('click', '#save3', function(){ 13 window.localStorage.setItem('text3', $("#list .text3").val()); 14 alert("データ3を保存しました。"); 15});

これでいかがでしょうか?

変更部分は
$("#save1").click(function(){

$(document).on('click', '#save1', function(){
に置き換えております。

少し気になって調べてみましたら、興味深い記事がありました。

jQueryのappendメソッドなどで後から追加した要素にclickイベントを設定するとクリックをしているのに動かないことがあります。

そういうときは、onメソッドを使うと解決できる

clickイベント(jQuery)の罠

私もこの問題で引っかかりそうでしたので大変勉強になりました。
頑張って開発を続けてくださいね。

投稿2017/01/17 15:37

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suisuin

2017/01/19 11:13

ありがとうございます。 リンク先拝見し勉強させていただきました。 指定のとおりに設定し、他もいろいろ触ったのですがおも通りに動かず今も頑張ってます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問