各ボタンから追加した各テキストエリアをlocalStorageで保存・削除を実行したい
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 1,962
各ボタンから追加した各テキストエリアを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個以上作る予定です。
}
上記のコードをもとに、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は置いといて各ボタンからテキストエリアのみを追加、さらにテキストエリアの内容の保存を試みたりしたのですがうまくいきません。
どうかご教授くださいますようよろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
まず初めに、これはlocalStorageに保存ができないのではなく
クリックイベントが付与できていないのが原因です。
#save(n)
に対するclickイベントがdocument.readyのタイミングで定義されていますが
#save(n)
はbuttonをクリックした際に追加される要素です。つまり、document.readyの段階ではページ上に存在していない要素です。
そのため、例え.on('click', fun)
で定義しようと、そのイベントは付与されません。(alertが実行されないのはその為です)
正しくは、append()
したタイミングで.on('click', fun)
を行う必要があります。
//Ex.
$("#list").append('<textarea id="text1" class="text1"></textarea><button id="save1">保存</button><button id="delete1" onClick="history.go(0)">削除</button>');
$('#save1').on('click', function(){
//クリック時の処理
});
とはいえ、この要素ごとにいちいち一つづつイベントを作成、付与していくのはあまりにも冗長かつ
無駄にメモリを使用するので、親要素でイベント管理するほうが良いかなと思います。
そこで、まずはHtmlから少し改善して
<!--各ボタンに対して共通クラスを付与。(ここでは.butoon)-->
<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>
//コード内でconst,letを使用していますが、そのままvarに置き換えてもOKです。
$(function() {
const wrapper = $('#list');
//documentではなく、上記Htmlの親要素のidでもOK
$(document).on('click', '.button, .save, .delete', function(){ //$(element)以下の.button, .save, .deleteを持つ要素すべてに対してクリックイベントを(この方法は後から追加された要素に対しても有効)
let elClass = $(this).attr('class') //クリックされた要素のクラス名を取得
let num = $('.'+elClass).index(this); //その要素が同一クラスを持つ要素の中で何番目か取得
let n = num + 1;
if( $(this).hasClass('button') ){ //.buttonなら
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、保存、削除用ボタンも共通クラスに変更
}else if( $(this).hasClass('save') ){ //.saveなら
let val = $("#list .text").eq(num).val();
localStorage.setItem('text'+n , val ); //window.は無くてOK
alert("データ"+n+"を保存しました。");
}else{ //.deleteなら
localStorage.removeItem('text'+n); // removeItem()の引数はkeyのみ(valueは不要)
alert("データ"+n+"を削除しました。");
}
});
});
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へ追加されているのが確認できない場合あり。注:保存はされている=リロードすると保存できているのが確認可)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
$(document).on('click', '#save1', function(){
window.localStorage.setItem('text1', $("#list .text1").val());
alert("データ1を保存しました。");
});
$(document).on('click', '#save2', function(){
window.localStorage.setItem('text2', $("#list .text2").val());
alert("データ2を保存しました。");
});
$(document).on('click', '#save3', function(){
window.localStorage.setItem('text3', $("#list .text3").val());
alert("データ3を保存しました。");
});
これでいかがでしょうか?
変更部分は
$("#save1").click(function(){
を
$(document).on('click', '#save1', function(){
に置き換えております。
少し気になって調べてみましたら、興味深い記事がありました。
jQueryのappendメソッドなどで後から追加した要素にclickイベントを設定するとクリックをしているのに動かないことがあります。
そういうときは、onメソッドを使うと解決できる
私もこの問題で引っかかりそうでしたので大変勉強になりました。
頑張って開発を続けてくださいね。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/19 21: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に変えて正常に動けば解決としたいのですが、どうか、引き続きお力添えいただけないでしょうか。
2017/01/19 22:01 編集
一応、キャプチャを回答文にも追記しました。
②が起こる時点でどこかの記述が違っている可能性があります。
あるいは、他のパートの要素に同一のクラスが使用されていないかも合わせてチェックしてみてください。
※内部処理的にそれぞれの保存ボタン、削除ボタンに番号を振って重複しないようにしてあるのが回答のコードです。
また、保存は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なので親要素ではありません。
2017/01/21 19:33
1. .buttonを変更
2.提示頂いたjavascriptの6行目、データが保存時のコードの4行目にセミコロンを入れる。
3. if( $(this).hasClass('button') ){ ...}の箇所へ「 localStorage.setItem("list", $("#list").html());」を追記
3は、片っ端から当てはめてみて試した結果です。ただ、意味はよく理解できてませんが
何においても解決できました。ありがとうございました。
2017/01/21 20: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名が重複しているのでどのボタンをクリックしても内容を上書きするということになるかと。
それでうまく行っているのであれば、提示していただいている内容と実際の環境に差異があるか、こちらが質問の内容を勘違いをしているかかなと思います。
2017/01/22 18:25
ただその前まで出来ていなかったことで、恐らくそれまで色々試していたコードが何か残っていて悪さをしていたのではと思います。
目的については、仰るとおりです。textarea内の内容がlocalStorageへ保存したかったのですが、回答をいただき動作を確認していくうちに 「リロードしてもwrapper.appendで追加された内容表示を残せないか」と思い色々試してました。これも原因に含まれると思います。
現状、ボタンをクリックしテキストエリアを追加 ⇒ 保存ボタンでテキストエリアの内容が保存 ⇒ リロードしたのちボタンをクリックすればテキストエリアの保存内容が確認できます。これをリロードしてもテキストエリアの表示を残したいと思いました。ただ当初の質問とは異なるのではと思いそこは触れずにいた次第です。 そこは自分で何とかできないかなと思い今挑戦しています。