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

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

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

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

Q&A

解決済

4回答

2096閲覧

javascriptで置換した文字列をもとに戻したい

shiramiso

総合スコア25

JavaScript

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

0グッド

1クリップ

投稿2018/05/19 02:12

javascript初学者です。
以下のように、クリックイベントを取得し関数でwebページ内の文字列をDOMで置換しています。

JAVASCRIPT

1$(function(){ 2 $('.changebutton'),on('click',function(){ 3 文字列置換処理 4 }

書き換えられたwebページをリフレッシュ以外で元に戻したいのですがどういったアプローチが可能でしょうか。

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

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

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

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

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

m.ts10806

2018/05/19 03:05

置換の処理も省略せずに追記してください。それによってやり方も考えなければなりません。
guest

回答4

0

眠い…。

HTML

1<tagname class="restorable" data-original="hogehage">hogehage</tagname>

Javascript

1$(function(){ 2 $(".changebutton").on("click", function() 3 { 4 // 文字列置換処理 5 }); 6 7 $(".restore").on("click", function() 8 { 9 $(".restorable").each(function() 10 { 11 $(this).text($(this).data("original")); 12 return true; 13 }); 14 }); 15})();

投稿2018/05/19 22:58

編集2018/05/19 23:53
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2018/05/20 04:44

もう、luckerお兄さんの回答が素晴らしすぎるなぁ…。根本的に次元が違うし。
退会済みユーザー

退会済みユーザー

2018/05/20 12:52

マイナス付けてる奴について、運営は何もしないんだよなぁ…。
退会済みユーザー

退会済みユーザー

2018/05/20 12:52

本当に、teratailの評価システムはクズ過ぎて話にならんな。
退会済みユーザー

退会済みユーザー

2018/05/20 12:53

運営が可哀そうだから文句言わないでいてやるだけって事、分かってるのかな?
Lhankor_Mhy

2018/05/22 05:37

最後の行にtypoありますよ。
退会済みユーザー

退会済みユーザー

2018/05/22 11:25

弘法も眠いと筆を誤るのです。 でも、そこは趣旨とは関係ないのでどうでもいいのです。
Lhankor_Mhy

2018/05/23 00:18 編集

普通に typo 指摘しただけなのですが、何かしらの意図をお感じになったのなら誤解です。 まあ、もしかして誤解されるかもなあ、という予想もしないでもなかったので、大して気にはしていないのですが。 そういうわけではなくて、lucker さんが typo 指摘を受ける度に何か一言言わないと気が済まないたちなのでしたら、失礼いたしました。
退会済みユーザー

退会済みユーザー

2018/05/23 12:14

typo指摘受ける如何にかかわらず何か一言いわないと気が済まないたちなのは知ってくるくせに。
Lhankor_Mhy

2018/05/23 12:55

そうなんですか。口が悪いだけの人だと思ってましたが、そら面倒ですね。
退会済みユーザー

退会済みユーザー

2018/05/23 22:15

そらもう、面倒ですよ。
guest

0

ベストアンサー

原則として、書き換える直前に「元の文字列」をバックアップします。

data-* 属性 -> input要素

.changebutton がbutton関係要素の値を書き換えている事を意図しているように感じたので、input要素の書き換え版。

HTML

1<p><input type="button" class="target" value="Hello, World!"><input type="button" class="change1" value="change"><input type="button" class="reset1" value="reset"></p> 2<p><input type="button" class="target" value="Hello, World!"><input type="button" class="change1" value="change"><input type="button" class="reset1" value="reset"></p> 3<p><input type="button" class="target" value="Hello, World!"><input type="button" class="change1" value="change"><input type="button" class="reset1" value="reset"></p> 4 5<script> 6'use strict'; 7jQuery('.change1').on('click', function (event) { 8 var input = event.target.parentNode.querySelector('.target'); 9 10 console.dir(input.attributes['data-defaultvalue']) 11 12 if (!input.attributes['data-defaultvalue']) { 13 input.setAttribute('data-defaultvalue', input.value); 14 } 15 16 input.value = input.value.replace(/World/g, 'JavaScript'); 17}); 18 19jQuery('.reset1').on('click', function (event) { 20 var input = event.target.parentNode.querySelector('.target'); 21 22 if (input.attributes['data-defaultvalue']) { 23 input.value = input.getAttribute('data-defaultvalue'); 24 } 25}); 26</script>

data-* 属性 -> テキストノード

親要素にテキストノード値を保存する。

HTML

1<p>Hello, World!<input type="button" class="change2" value="change"><input type="button" class="reset2" value="reset"></p> 2<p>Hello, World!<input type="button" class="change2" value="change"><input type="button" class="reset2" value="reset"></p> 3<p>Hello, World!<input type="button" class="change2" value="change"><input type="button" class="reset2" value="reset"></p> 4 5<script> 6'use strict'; 7jQuery('.change2').on('click', function (event) { 8 var p = event.target.parentNode, 9 textNode = p.firstChild; 10 11 if (!p.attributes['data-defaultvalue']) { 12 p.setAttribute('data-defaultvalue', textNode.data); 13 } 14 15 textNode.data = textNode.data.replace(/World/g, 'JavaScript'); 16}); 17 18jQuery('.reset2').on('click', function (event) { 19 var p = event.target.parentNode; 20 21 if (p.attributes['data-defaultvalue']) { 22 p.firstChild.data = p.getAttribute('data-defaultvalue'); 23 } 24}); 25</script>

祖先要素にテキストノード値を保存する。

HTML

1<p class="parent">Good morning, World! <span>Hello, World!</span> Good evening, World!<input type="button" class="change3" value="change"><input type="button" class="reset3" value="reset"></p> 2<p class="parent">Good morning, World! <span>Hello, World!</span> Good evening, World!<input type="button" class="change3" value="change"><input type="button" class="reset3" value="reset"></p> 3<p class="parent">Good morning, World! <span>Hello, World!</span> Good evening, World!<input type="button" class="change3" value="change"><input type="button" class="reset3" value="reset"></p> 4 5<script> 6'use strict'; 7jQuery('.change3').on('click', function (event) { 8 var p = event.target.parentNode, 9 textNodeSnapshot = p.ownerDocument.evaluate('descendant::text()', p, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 10 11 if (!p.attributes['data-defaultvalue']) { 12 var textList = []; 13 14 for (var i = 0, len = textNodeSnapshot.snapshotLength; i < len; ++i) { 15 var textNode = textNodeSnapshot.snapshotItem(i); 16 17 textList.push(textNode.data); 18 textNode.data = textNode.data.replace(/World/g, 'JavaScript') 19 } 20 21 p.setAttribute('data-defaultvalue', JSON.stringify(textList)); 22 } else { 23 for (var i = 0, len = textNodeSnapshot.snapshotLength; i < len; ++i) { 24 var textNode = textNodeSnapshot.snapshotItem(i); 25 26 textNode.data = textNode.data.replace(/World/g, 'JavaScript') 27 } 28 } 29}); 30 31jQuery('.parent').on('click', function (event) { 32 var input = event.target; 33 34 if (!input.classList.contains('reset3')) { 35 return; 36 } 37 38 var p = event.currentTarget; 39 40 if (p.attributes['data-defaultvalue']) { 41 var textList = JSON.parse(p.getAttribute('data-defaultvalue')), 42 textNodeSnapshot = p.ownerDocument.evaluate('descendant::text()', p, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), 43 len = textNodeSnapshot.snapshotLength; 44 45 if (textList.length !== len) { 46 throw new Error; 47 } 48 49 for (var i = 0; i < len; ++i) { 50 textNodeSnapshot.snapshotItem(i).data = textList[i]; 51 } 52 } 53}); 54</script>

このコードは、要素とテキストノードが1対1でない場合に有効に働かない事を意味しています。
バックアップした後に動的にテキストノードが増減したら、破綻してしまうからです。

WeakMap -> テキストノード

WeakMap を使う事でテキストノードに「元の文字列」を保存することが出来ます。

HTML

1<p class="parent">Good morning, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"> <span>Hello, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"></span> Good evening, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"></p> 2<p class="parent">Good morning, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"> <span>Hello, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"></span> Good evening, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"></p> 3<p class="parent">Good morning, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"> <span>Hello, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"></span> Good evening, World!<input type="button" class="change4" value="change"><input type="button" class="reset4" value="reset"></p> 4 5<script> 6'use strict'; 7(function () { 8 function handleClick1 (event) { 9 var input = event.target, 10 textNode = input.previousSibling, 11 wm = event.data; 12 13 if (!wm.has(textNode)) { 14 wm.set(textNode, textNode.data); 15 } 16 17 textNode.data = textNode.data.replace(/World/g, 'JavaScript'); 18 } 19 20 function handleClick2 (event) { 21 var input = event.target, 22 textNode = input.previousSibling.previousSibling, 23 wm = event.data; 24 25 if (wm.has(textNode)) { 26 textNode.data = wm.get(textNode); 27 } 28 } 29 30 function main () { 31 var wm = new WeakMap; 32 33 jQuery('.change4').on('click', wm, handleClick1); 34 jQuery('.reset4').on('click', wm, handleClick2); 35 } 36 37 main.call(this); 38}.call(this)); 39</script>

Re: KShiramiz さん

投稿2018/05/22 14:02

think49

総合スコア18166

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

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

退会済みユーザー

退会済みユーザー

2018/05/23 12:15 編集

luckerお兄さんのパクリじゃないかっ!
shiramiso

2018/05/25 10:33

ありがとうございます。やはりバックアップしておく必要があるのですね。。 逆置換は検討していたのですが、もし変換前のDOMに戻る機能があればと思い… サンプルコードもいただきとても分かりやすかったです。ありがとうございました。
guest

0

置換をしないで表示だけ入れ替える、というのはどうでしょうか。

html

1<div id="a">置換前</div> 2<div id="b" class="hide">置換後(実は置換していない)</div> 3<div id="change">置換する</div> 4<div id="undo">戻す</div>

js

1$('#b').hide(); 2$('#change').on('click',function(){ 3 $('#b').show(); 4 $('#a').hide(); 5}); 6$('#undo').on('click',function(){ 7 $('#a').show(); 8 $('#b').hide(); 9});

投稿2018/05/19 08:52

Lhankor_Mhy

総合スコア36134

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

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

退会済みユーザー

退会済みユーザー

2018/05/20 01:19

んと、ごちゃごちゃして汚くなりそうじゃないかなかな?
think49

2018/05/20 23:59

すみません、また+評価→ゼロ評価をやってしまいました。 モバイル端末での操作は気をつける必要がありますね…。 後程、代替案を回答します。
Lhankor_Mhy

2018/05/21 00:35

システム上許されている操作なのですから、乱用したわけでもなく特段問題はないのでは、と思います。 Mutationobserver で監視して、MutationRecord を履歴としてログっておく、というのを思いついたのですが、非現実的すぎてやめました。
guest

0

思いつく手法とその問題点を羅列してみました。
① 置き換え前のDOMを保存しておく。
- 置き換え前のDOMを保存したDOMを特定できる一意のKeyを用意する必要がある
- DOMを保存するのでコストが高い
- 正直スマートではない(笑

② 置き換え後の文字列が一意に特定できるものであれば現在の状態を判断して逆置換をかける
処理を実装する。
- 置き換え後の文字列が元の文字列に出現する場合、逆置換すると異なるDOMになってしまう。

③ DOMの文字列置換をそもそも止め、DOM自体の表示、非表示を切り替えることで同様の機能を実装する。
- 用途や書き方によってはhtmlソースやJavascriptが汚くなる。

④ 置き換え対象のDOMや文字列が決め打ちして問題無いものであれば決め打ちで置き換え処理、逆置換処理を実装する。
- 決め打ちになるので使えるケースが限られてくる。

など、普通過ぎてあんまり中身ないですね 汗

投稿2018/05/19 08:53

nitoage

総合スコア98

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

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

nitoage

2018/05/19 08:55

必要であればコメントいただければsampleソースを添付します。
退会済みユーザー

退会済みユーザー

2018/05/20 01:20

んと、ごちゃごちゃして汚くなりそうじゃないかなかな?
shiramiso

2018/05/25 10:34

概念的なところを知りたかったので、拙い質問に対して的を射たご回答をしてくださり、とても助かりました。プロコンもまとめていただき、とても分かりやすかったです。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問