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

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

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

Backbone.jsはRESTfulなウェブアプリケーションを構築するJavaScriptフレームワークです。

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

2542閲覧

Backbone.jsでボタンのactive状態を変化させる方法

tarotarosu

総合スコア114

Backbone.js

Backbone.jsはRESTfulなウェブアプリケーションを構築するJavaScriptフレームワークです。

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2016/10/13 02:28

編集2016/10/13 10:00

###前提・実現したいこと
Backbone.js初学習者です。
JavaScript(jQuery)でコーディングしていたのですが、結構な量のDOM操作とAjax通信になってきたため、そのような状態からでも導入できそうなフレームワークを探していたところ、Backbone.jsにたどり着きました。
そこで、Backbone.js導入の第一歩として、以下のような処理を実装しよう試みました。
①id="btn-get-size"のボタンをクリック
②idをもとにxmlファイルからサイズ(数値)を取得し、そのサイズを描画する
③描画されたサイズをクリックするとchosenプロパティが変化し、activeクラスが付与され、色が変化する
④その状態でほかのボタンをクリックするとそのサイズにactiveクラスが付与され、先ほどクリックしたサイズの色が消える(つまり、クリックしたサイズ以外は色変化させたくないということです)

上記の中で問題となっているのが③、④です。同じサイズを連続でクリックした場合は色が消えないようにしたいのです。
(簡単に言うと、色がつくのはクリックしたものだけ。ということです)
私の書いたコードですと、同じものをクリックすると色が消えてしまいます。(当たり前といえば当たり前なのかもしれませんが...)

個人的な考えでは、「サイズがクリックされたとき描画されている全モデルのchosenプロパティをfalseにし、その後でクリックしたもののchosenプロパティをtureにし、renderしなおす。」
という方法で実現できるのではないかと考えているのですが、Backbone.jsでそれをどう記述してやればいいのかがわかりません...
(そもそもBackbone.jsを使っていて、$(".size-selector").find(".btn-size").removeClass("active"); などとしている時点でかなりナンセンスですよね...)

どなたか、解決策を教えていただけると非常に助かります_(..)

###該当のソースコード

javascript

1(function(){ 2 //Model 3 var Size = Backbone.Model.extend({ 4 defaults: { 5 size: "", 6 chosen: false 7 } 8 }); 9 10 //Collection 11 var Sizes = Backbone.Collection.extend({ 12 model: Size 13 }); 14 15 //ModelのView 16 var SizeView = Backbone.View.extend({ 17 tagName: 'li', 18 template: _.template($('#size-template').html()), 19 initialize: function(){ 20 this.model.on('change', this.render, this) 21 }, 22 events: { 23 'click .btn-size': 'toggle' 24 }, 25 toggle: function(){ 26 //ここで全部falseにする必要あり? 27 $(".size-selector").find(".btn-size").removeClass("active"); 28 29 if (this.model.get('chosen') == false) { 30 this.model.set('chosen', true); 31 } 32 else { 33 this.model.set('chosen', false); 34 } 35 }, 36 render: function(){ 37 var template = this.template(this.model.toJSON()); 38 this.$el.html(template); 39 return this; 40 } 41 }); 42 43 //CollectionのView 44 var SizesView = Backbone.View.extend({ 45 tagName: 'ul', 46 render: function(){ 47 this.collection.each(function(size){ 48 var sizeView = new SizeView({model: size}); 49 this.$el.append(sizeView.render().el); 50 }, this); 51 return this; 52 } 53 }); 54 55 //ボタンのView 56 var ShapeBtnView = Backbone.View.extend({ 57 el: '#show-size', 58 events: { 59 'click #btn-get-size': 'getSize' 60 }, 61 getSize: function(){ 62 //シェイプidを付与 63 SHAPE.id = 'test01'; 64 //サイズCollectionを生成 65 var sizes = new Sizes(); 66 67 ajax_processing('size.xml', function(xml){ 68 $(xml).find('shape[code="' + SHAPE.id + '"] > SizeList > Size').each(function(){ 69 //サイズ格納 70 var size = $(this).attr('size'); 71 72 //取得したサイズをプロパティに設定して、sizeインスタンスを生成 73 var size = new Size({size: size, chosen: false}); 74 75 //sizeをCollectionに追加 76 sizes.add(size); 77 }); 78 //Collectionをrender 79 var sizesView = new SizesView({collection: sizes}); 80 $('.size-selector').append(sizesView.render().el); 81 }); 82 } 83 }); 84 85 //インスタンス生成 86 var shapeBtnView = new ShapeBtnView(); 87})(); 88

html

1<div id="show-size"> 2 <button type="button" id="btn-get-size" class="btn btn-primary">Size一覧表示</button> 3</div> 4<h3>Backbonejs Demo</h3> 5<div class="size-selector"> 6 <!-- ここに挿入 --> 7</div> 8 9<script type="text/template" id="size-template"> 10 <div class="btn-size <%= chosen ? 'active' : '' %>"> 11 <%- size %> 12 </div> 13</script>

###追記
ajax_processing関数とは以下のようなものです。

javascript

1function ajax_processing(url, fn) { 2 $.ajax({ 3 url: url, 4 type: "GET", 5 dataType: "xml", 6 timeout: 1000, 7 error: function(){ 8 alert("ロード失敗"); 9 }, 10 success: fn 11 }); 12} 13

###追記2
追記2のようにSizesViewのコードを修正したところ、chosenプロパティがtrueのものをfalseにして、renderし直すことはできました。
おそらく、追加したhogeメソッドの中で、クリックされたmodelのchosenプロパティをtrueにしてrenderし直すことができれば、考えていたことが実現できそうなのですが…

javascript

1var SizesView = Backbone.View.extend({ 2 tagName: 'ul', 3 events: { 4 'click .btn-size': 'hoge' 5 }, 6 hoge: function(){ 7 var sizes = this.collection.where({'chosen': true}); 8 _.each(sizes, function(size){ 9 size.set('chosen', false); 10 var sizeView = new SizeView({model: size}); 11 sizeView.render(); 12 }); 13 }, 14 render: function(){ 15 this.collection.each(function(size){ 16 var sizeView = new SizeView({model: size}); 17 this.$el.append(sizeView.render().el); 18 }, this); 19 return this; 20 } 21 }); 22

###追記3
何度も追記してすみません。
実現したいこととしては、下記サイトのようなことです。
しかし、CoffeeScriptがさっぱりなのと、このような複雑そうなことをしなければならないのか疑問で…
Backbone.jsでUIの状態を管理するみたいなやつ

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

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

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

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

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

guest

回答2

0

自己解決

下記のコードのように、Sizeモデルからchosenプロパティを削除し、SizesView内にactive状態を管理するactiveOperationメソッドを追加することで、何とか実現したいことは実現しました。
初期のコードから結構修正を加えた上に、これがBackbone.jsを使う上でスマートなやり方なのかわからない(おそらくプロパティ値から変更する方法のほうがスマートなのだろうとは思います)ので、その他の解決策がありましたら教えていただけますと非常に助かります_(..)

javascript

1//サイズModel 2var Size = Backbone.Model.extend({ 3 defaults: { 4 size: "" 5 //chosenプロパティを削除 6 } 7}); 8 9//サイズCollection 10var Sizes = Backbone.Collection.extend({ 11 model: Size 12}); 13 14//サイズModelのView 15var SizeView = Backbone.View.extend({ 16 tagName: 'li', 17 template: _.template($('#size-template').html()), 18 render: function(){ //toggleした場合もrenderし直す 19 var template = this.template(this.model.toJSON()); 20 this.$el.html(template); 21 return this; 22 } 23}); 24 25//サイズCollectionのView 26var SizesView = Backbone.View.extend({ 27 tagName: 'ul', 28 //ここから修正 29 events: { 30 'click .btn-size': 'activeOperation' 31 }, 32 activeOperation: function(){ 33 //一旦active状態を解除 34 this.$('.active').removeClass('active'); 35 //クリックされたものをactive状態に 36 var target = $(event.target); 37 target.addClass('active'); 38 }, 39 //ここまで修正 40 render: function(){ 41 this.collection.each(function(size){ 42 var sizeView = new SizeView({model: size}); 43 this.$el.append(sizeView.render().el); 44 }, this); 45 return this; 46 } 47}); 48 49

投稿2016/10/14 02:24

tarotarosu

総合スコア114

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

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

0

同じサイズを連続でクリックした場合は色が消えないようにしたい

上記に対する回答のみになってしまいますが、toggle メソッドのなかで model の chosentrue なときは return してしまうとよいのではないでしょうか。

toggle: function(){ // 追記 if(this.model.get('chosen')) { return; } // 追記ここまで //ここで全部falseにする必要あり? $(".size-selector").find(".btn-size").removeClass("active"); if (this.model.get('chosen') == false) { this.model.set('chosen', true); } else { this.model.set('chosen', false); } },

return 以降の処理は走らなくなるので色が元に戻ることもなくなりそうです

投稿2016/10/13 07:22

machine_machine

総合スコア162

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

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

tarotarosu

2016/10/13 09:37

確かにその点だけで言うと意図した動きになるのですが... やりたいこととしては下記サイトのようなものなのです。 http://hamalog.tumblr.com/post/19008960974/backbonejs%E3%81%A7ui%E3%81%AE%E7%8A%B6%E6%85%8B%E3%82%92%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B%E3%81%BF%E3%81%9F%E3%81%84%E3%81%AA%E3%82%84%E3%81%A4 しかし、CoffeeScriptはさっぱりわからないのと、こんな複雑そうなことをいなければならないのかと疑問に思ってしまって...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問