/**
* @author Akihiro Oyamada
*/
;( function () {
'use strict';
var observer = _.clone( Backbone.Events );
var isOldIe = ( document.documentMode < 9 );
var forceIe8Repaint = function () {
if ( isOldIe ) {
return function ( $elm ) {
$elm.hide();
$elm.removeAttr( 'style' );
}
} else {
return function () {}
}
}();
$( function () {
//
// グリッドビューの絞り込み機能
//
var model = new ( Backbone.Model.extend( {
defaults: {
selected : 'menu-latest'
},
_LOOKUP: [
'menu-latest',
'menu-products',
'menu-store',
'menu-mysony'
]
} ) );
var view = new ( Backbone.View.extend( {
events: {
'click .home-Main__menuButton': 'tabChange',
'click button[role="menuitemradio"]': 'tabChange'
},
el: '.home-Main',
initialize: function () {
var $win = $( window );
this._$navViewPort = this.$el.find( '.home-Main__menuInner' );
this._$nav = this.$el.find( '.home-Main__menuInner ul' );
this._$buttons = this.$el.find( '.home-Main__menuButton' );
this._$items = this.$el.find( '.home-GridItem' );
this._$ssrItems = this.$el.find( '.home-GridContentSonyStoreArea__list li' );
this.matchHeight();
this.listenTo( model, 'change', this.updateView );
$win.on( 'resize', _.throttle( this.matchHeight.bind( this ), 190 ) );
$win.one( 'load', this.matchHeight.bind( this ) );
var selected = model.get( 'selected' );
},
tabChange: function ( e ) {
var $button = $( e.target );
location.hash = '#' + $button.attr( 'id' ).replace( /^menu-/, '' );
},
matchHeight: function () {
var $items = this._$items.filter( ':visible' );
var currentRowOffset = -1 | 0;
var rowGroup = [];
$items.removeAttr( 'style' );
$items.each( function () {
var $this = $( this );
var offsetTop = $this.offset().top | 0;
if ( currentRowOffset !== offsetTop ) {
currentRowOffset = offsetTop;
rowGroup.push( {
maxHeight: 0,
els: []
} );
}
rowGroup[ rowGroup.length - 1 ].maxHeight = Math.max(
rowGroup[ rowGroup.length - 1 ].maxHeight,
$this.outerHeight()
);
rowGroup[ rowGroup.length - 1 ].els.push( $this );
} );
_.forEach( rowGroup, function ( group ) {
if ( group.els.length === 1 ) { return; }
_.forEach( group.els, function ( $el ) {
$el.css( { height: group.maxHeight } );
} );
} );
// 「ソニーストアのおすすめ」ないの
// 実施中のキャンペーン・おすすめ商品 / 店舗ならではのサービス・イベント
// 横並び要素の高さを合わせる必要がある
var $ssrItem = this._$ssrItems.filter(':visible');
var ssrCurrentRowOffset = -1 | 0;
var ssrGroup = [];
var ssrGroupId = [];
$ssrItem.removeAttr('style');
$ssrItem.each(function () {
var $this = $(this);
var offsetTop = $this.offset().top | 0;
if (ssrGroupId.indexOf(offsetTop) === -1) {
ssrGroup.push({
offsetT: offsetTop,
maxHeight: $this.outerHeight(),
els: []
});
ssrGroup[ssrGroup.length - 1].els.push($this);
ssrGroupId.push(offsetTop);
} else {
_.forEach(ssrGroup, function (group, index) {
if (offsetTop === group.offsetT) {
ssrGroup[index].maxHeight = Math.max(
ssrGroup[index].maxHeight,
$this.outerHeight()
);
ssrGroup[index].els.push($this);
}
});
}
});
_.forEach(ssrGroup, function (group) {
if (group.els.length === 1) { return; }
_.forEach(group.els, function ($el) {
$el.css({ height: group.maxHeight });
});
});
},
fitNavLeft: function () {
var selected = model.get( 'selected' );
var $button = this._$buttons.filter( '#' + selected );
var scrollLeft = this._$navViewPort.scrollLeft();
var buttonLeft = $button.offset().left;
var left = buttonLeft + scrollLeft - 20;
// 旧Androidバグ対応
// http://stackoverflow.com/questions/12225456/jquery-scrolltop-does-not-work-in-scrolling-div-on-mobile-browsers-alternativ
this._$navViewPort.css( { overflow: 'hidden' } );
$.when(
this._$navViewPort.animate( {
scrollLeft: left
}, 300, 'easeOutQuart' )
).done( function () {
this._$navViewPort.css( { overflow: '' } );
}.bind( this ) );
},
scrollTo: function () {
var $win = $( window );
var $html = $( 'html, body' );
return function () {
var targetY = this.$el.offset().top;
var scrollTop = $win.scrollTop();
if ( scrollTop < targetY ) { return; }
$html.animate( {
scrollTop: targetY
}, 500, 'easeOutQuart' );
}
}(),
updateView: function () {
var selected = model.get( 'selected' );
this._$buttons.each( function () {
var $this = $( this );
var _selected = ( $this.attr( 'id' ) === selected );
$this.parent().attr( {
'aria-checked': _selected
} );
} );
this._$items.each( function () {
var $this = $( this );
var labelledby = $this.attr( 'data-grid-item-type' );
var pattern = new RegExp( '\\b' + selected + '\\b' );
if ( pattern.test( labelledby ) ) {
$this.attr( { 'aria-hidden': false } );
} else {
$this.attr( { 'aria-hidden': true } );
}
} );
observer.trigger( 'gridviewchange', { selected: selected } );
// IE8は、属性セレクタにフックされたスタイルがアップデートされない。
// そのため強制再描画が必要。
forceIe8Repaint( this.$el );
this.matchHeight();
this.fitNavLeft();
this.scrollTo();
}
} ) );
// スワイプで切り替える
var touchHandlerView = new ( Backbone.View.extend( {
el: '.home-Main__body',
$win: $( window ),
event: {
start: 'pointerdown MSPointerDown touchstart mousedown',
move : 'pointermove MSPointerMove touchmove mousemove',
end : 'pointerup MSPointerUp touchend mouseup'
},
pointerId: null,
isActive: false,
startPosition: { x: 0, y: 0 },
xThreshold : 80,
allowedY : 30,
initialize: function () {
if ( isOldIe ) { return; }
var onbuttondown = function ( event ) {
this.isActive = true;
if ( event.originalEvent.pointerId ) {
this.pointerId = event.originalEvent.pointerId;
} else if ( event.originalEvent.changedTouches ) {
this.pointerId = event.originalEvent.changedTouches[ event.originalEvent.changedTouches.length - 1 ].identifier;
}
var coordinate = this.getEventCoordinate( event );
if ( !coordinate ) { return; }
this.startPosition.x = coordinate.x;
this.startPosition.y = coordinate.y;
this.$win.on( this.event.move, onbuttonmove );
this.$win.on( this.event.end, onbuttonup );
}.bind( this );
var onbuttonmove = function ( event ) {
var coordinate = this.getEventCoordinate( event );
if ( !coordinate ) {
reset();
return;
}
if ( this.allowedY < Math.abs( coordinate.y - this.startPosition.y ) ) {
reset();
return;
}
var distX = coordinate.x - this.startPosition.x;
if ( this.xThreshold < Math.abs( distX ) ) {
var isSwipeLeft = ( distX < 0 );
var selected = model.get( 'selected' );
var currentIndex = model._LOOKUP.indexOf( selected );
var fac = isSwipeLeft ? 1 : -1;
var nextIndex = ( currentIndex + fac + model._LOOKUP.length ) % model._LOOKUP.length;
location.hash = '#' + model._LOOKUP[ nextIndex ].replace( /^menu-/, '' );
event.preventDefault();
event.stopPropagation();
reset();
return;
}
}.bind( this );
var onbuttonup = function ( event ) {
reset();
}.bind( this );
var reset = function () {
this.$win.off( this.event.move, onbuttonmove );
this.$win.off( this.event.end, onbuttonup );
this.isActive = false;
this.startPosition.x = 0;
this.startPosition.y = 0;
}.bind( this );
this.$el.on( this.event.start, onbuttondown );
},
getEventCoordinate: function ( event ) {
var x, y, _event = null, i, l;
if ( event.originalEvent.pointerId ) {
if ( this.pointerId === event.originalEvent.pointerId ) {
_event = event.originalEvent;
}
} else if ( event.originalEvent.changedTouches ) {
for ( i = 0, l = event.originalEvent.changedTouches.length; i < l; i ++ ) {
if ( this.pointerId === event.originalEvent.changedTouches[ i ].identifier ) {
_event = event.originalEvent.changedTouches[ i ];
}
}
} else {
_event = event;
}
if ( _event === null ) {
return false;
}
x = _event.clientX;
y = _event.clientY;
return { x: x, y: y };
}
} ) );
var router = new (Backbone.Router.extend( {
routes : {
'latest' : 'latest',
'products': 'products',
'store' : 'store',
'mysony' : 'mysony'
},
latest: function latest() {
model.set( { selected: 'menu-latest' } );
},
products: function products() {
model.set( { selected: 'menu-products' } );
},
store: function store () {
model.set( { selected: 'menu-store' } );
},
mysony : function mysony () {
model.set( { selected: 'menu-mysony' } );
}
} ) );
var renderAdobeTarget = function () {
var $recentlyViewed = $('.home-GridContentRecentlyViewed');
var $item = $recentlyViewed.closest('.at-element-marker');
// divタグで囲っていたのをliタグに変更
var tag_class = $item.attr('class');
var tag_class_plus = '';
if (tag_class != null) {
tag_class_plus = 'class="' + tag_class + '"';
}
//指定した要素の子要素に親要素を追加、その後、自身のclassを全削除
$item.wrapInner('
').removeClass();
// $itemを取り直し、不要になった大外のdivタグを削除
$item = $recentlyViewed.closest('.at-element-marker');
$item.unwrap();
// 名もなきdivにstyleを付与。
$item.children('div').css({
height: '100%'
});
// Adobe target が生成したDOMにclassをつけてレイアウトを整える
$item = $item.addClass('home-GridItem');
if ((location.hash === '#latest') || (location.hash === '')) {
$item = $item.addClass('home-GridItem--SSpan2of2');
$item = $item.addClass('home-GridItem--LSpan4of6');
$item.attr({
'data-grid-item-type': 'menu-products menu-latest',
'aria-hidden': false
});
} else if (location.hash === '#products') {
$item = $item.addClass('home-GridItem--LSpan2of6');
$item = $item.addClass('home-GridItem--LSpan4of6');
$item.attr({
'data-grid-item-type': 'menu-products menu-latest',
'aria-hidden': false
});
} else if ((location.hash === '#store') || (location.hash === '#mysony')) {
$item.attr({
'data-grid-item-type': 'menu-products menu-latest',
'aria-hidden': true
});
}
view.initialize();
}
// AdobeTarget の同期的な実行
if (typeof adobe !== 'undefined') {
if (typeof adobe.target !== 'undefined') {
if (typeof adobe.target.event !== 'undefined') {
// Content Rendering Succeeded 時に取得できるカスタムイベントを利用
if (typeof adobe.target.event.CONTENT_RENDERING_SUCCEEDED !== 'undefined') {
document.addEventListener(adobe.target.event.CONTENT_RENDERING_SUCCEEDED, function () {
renderAdobeTarget();
});
}
}
}
}
renderAdobeTarget();
Backbone.history.start();
} );
$( function () {
// 「商品を探す」
// - 大画面向け
// - タブ切り替え(ラジオ形式)
// - ブロック高さ合わせ
// - 小画面向け
// - タブ切り替え(チェック形式)
// - スライド切り替え
var Model = Backbone.Model.extend( {
defaults: {
buttonId : null,
panelId : null,
isVisible : false,
needsAnimUpdate: false
}
} );
var collection = new ( Backbone.Collection.extend( {
checkAsRadio: function ( id ) {
var model = this.findWhere( { buttonId: id } );
if ( model.get( 'isVisible' ) === true ) {
return;
}
this.forEach( function ( _model ) {
if ( model === _model ) {
_model.set( {
isVisible: true,
needsAnimUpdate: true
}, { silent: true } );
} else {
var needsAnimUpdate = ( _model.get( 'isVisible' ) === true );
_model.set( {
isVisible: false,
needsAnimUpdate: needsAnimUpdate
}, { silent: true } );
}
} );
this.trigger( 'change' );
},
checkAsCheck: function ( id ) {
var model = this.findWhere( { buttonId: id } );
var isVisible = model.get( 'isVisible' );
this.forEach( function ( _model ) {
if ( model === _model ) {
_model.set( {
isVisible: !isVisible,
needsAnimUpdate: true
}, { silent: true } );
} else {
_model.set( {
needsAnimUpdate: false
}, { silent: true } );
}
} );
this.trigger( 'change' );
},
toRadioList: function () {
var model = this.findWhere( { isVisible: true } );
if ( !!model ) {
collection.forEach( function ( _model ) {
if ( model !== _model ) {
_model.set( { 'isVisible': false } );
}
} );
} else {
collection.forEach( function ( _model, i ) {
if ( i === 0 ) {
_model.set( { 'isVisible': true } );
} else {
_model.set( { 'isVisible': false } );
}
} );
}
}
} ) );
// 商品一覧ビュー
// var view = new ( Backbone.View.extend( {
//
// events: {
// 'click button[role="tab"]' : 'tabChange'
// },
//
// el: '.home-GridContentAllProducts',
//
// initialize: function () {
//
// this.listenTo( collection, 'change', this.updateView );
// $( window ).on( 'resize', _.throttle( this.matchHeight.bind( this ), 200 ) );
//
// // 大画面時は少なくともタブが1つが表示されていなければならないが、
// // 小画面、中画面時はすべてのタブ消すことができる。
// // 「小画面 -> 大画面」切り替わり時に全タブが消えている場合、一つのタブを選択状態にする。
// s5.vent.on( 'onmediachange:tobase onmediachange:tolarge', function () {
//
// collection.toRadioList();
//
// } );
//
// // 小画面、中画面では高さ揃えで付与されたstyle属性のheightが邪魔になるため
// // 「大画面 -> 小画面|中画面」切り替わり時に削除
// s5.vent.on( 'onmediachange:tomiddle onmediachange:tosmall', function () {
//
// if ( isOldIe ) { return; }
//
// var $item = this.$el.find( '.home-GridContentAllProducts__navLv2Item' );
// $item.removeAttr( 'style' );
//
// }.bind( this ) );
//
// // グリッド絞り込みにより、表示されたタイミングで高さ揃えを実行
// observer.on( 'gridviewchange', function ( e ) {
//
// if ( e.selected === 'menu-products' ) { this.matchHeight(); }
//
// }.bind( this ) );
//
// this.initCollection();
// this.matchHeight();
//
// },
//
// initCollection: function () {
//
// var $buttons = this.$el.find( 'button[role="tab"]' );
// $buttons.each( function () {
//
// var model = new Model( {
// buttonId : $( this ).attr( 'id' ),
// panelId : $( this ).attr( 'aria-controls' ),
// isVisible: ( $( this ).attr( 'aria-selected' ) === 'true' )
// } );
// collection.add( model );
//
// } );
//
// },
//
// tabChange: function ( e ) {
//
// var $button = $( e.target );
// var selectedButtonId = $button.attr( 'id' );
//
// // 大画面時はチェックボタン形式ではなくラジオボタン形式の選択
// // - 同じものが選択されると何も起こらない
// // - 少なくとも一つが選択された状態
// // - 一つを選択するとその他の選択が削除される
// if ( /(base|large)/.test( s5.getCurrentScreenType() ) || isOldIe ) {
//
// collection.checkAsRadio( selectedButtonId );
// return;
//
// }
// // 小画面、中画面時はチェックボタン形式の選択
// // - 同じものが選択される状態をトグルする
// // - 一つを選択しても、他の項目の状態はそのまま
// if ( /(small|middle)/.test( s5.getCurrentScreenType() ) && !isOldIe ) {
//
// collection.checkAsCheck( selectedButtonId );
// return;
//
// }
//
// },
//
// matchHeight: function () {
//
// if ( /(small|middle)/.test( s5.getCurrentScreenType() ) || isOldIe ) {
//
// return;
//
// }
//
// var selectedModel = collection.findWhere( { isVisible: true } );
// var $selectedPanel = this.$el.find( '#' + selectedModel.get( 'panelId' ) );
// var $item = $selectedPanel.find( '.home-GridContentAllProducts__navLv2Item' );
// var currentRowOffset = -1 | 0;
// var rowGroup = [];
//
// $item.removeAttr( 'style' );
//
// $item.each( function () {
//
// var $this = $( this );
// var offsetTop = $this.offset().top | 0;
//
// if ( currentRowOffset !== offsetTop ) {
//
// currentRowOffset = offsetTop;
// rowGroup.push( {
// maxHeight: 0,
// els: []
// } );
//
// }
//
// rowGroup[ rowGroup.length - 1 ].maxHeight = Math.max(
// rowGroup[ rowGroup.length - 1 ].maxHeight,
// $this.outerHeight()
// );
// rowGroup[ rowGroup.length - 1 ].els.push( $this );
//
// } );
//
// _.forEach( rowGroup, function ( group ) {
//
// _.forEach( group.els, function ( $el ) {
//
// $el.css( { height: group.maxHeight } );
//
// } );
//
// } );
//
// this.$el.css( {
// minHeight: $selectedPanel.height()
// } );
//
// },
//
// scrollToTop: function () {
//
// var $win = $( window );
// var $html = $( 'html, body' );
//
// return function () {
//
// if ( /(small|middle)/.test( s5.getCurrentScreenType() ) && !isOldIe ) {
//
// return;
//
// }
//
// var targetY = this.$el.offset().top;
// var scrollTop = $win.scrollTop();
//
// if ( scrollTop < targetY ) { return; }
//
// $html.animate( {
// scrollTop: targetY
// }, 500, 'easeOutQuart' );
//
// }
//
// }(),
//
// slideToggle: function () {
//
// if ( /(base|large)/.test( s5.getCurrentScreenType() ) ) {
//
// return;
//
// }
//
// collection.forEach( function ( model ) {
//
// if ( model.get( 'needsAnimUpdate' ) ) {
//
// var isVisible = model.get( 'isVisible' )
// var $panel = this.$el.find( '#' + model.get( 'panelId' ) );
//
// if ( isVisible ) {
//
// $panel.hide();
// $.when(
// $panel.slideDown()
// ).done( function () {
//
// $panel.removeAttr( 'style' );
//
// } );
//
// } else {
//
// $panel.show();
// $.when(
// $panel.slideUp()
// ).done( function () {
//
// $panel.removeAttr( 'style' );
//
// } );
//
// }
//
// }
//
// }.bind( this ) );
//
// },
//
// updateView: function () {
//
// collection.forEach( function ( model ) {
//
// var isVisible = model.get( 'isVisible' );
// var $button = this.$el.find( '#' + model.get( 'buttonId' ) );
// var $panel = this.$el.find( '#' + model.get( 'panelId' ) );
//
// $button.attr( {
// 'aria-selected': isVisible,
// 'aria-expanded': isVisible
// } );
// $panel.attr( {
// 'aria-hidden': !isVisible
// } );
//
// }.bind( this ) );
//
// this.matchHeight();
// this.scrollToTop();
// this.slideToggle();
// forceIe8Repaint( this.$el );
//
// }
//
// } ) );
} );
$( function () {
var doSetAdobeAndPageExecution = function () {
var $recentlyViewed = $('.home-GridContentRecentlyViewed');
var $item = $recentlyViewed.closest('.at-element-marker');
// 読み込みの時もカレントのタブを見てadd classするfunction
function doSetClassAdobeTarget(e) {
if (e.selected === 'menu-products') {
$item.removeClass('home-GridItem--LSpan4of6');
$item.addClass('home-GridItem--LSpan2of6');
} else {
$item.addClass('home-GridItem--LSpan4of6');
$item.removeClass('home-GridItem--LSpan2of6');
}
}
// loadした時に実行
observer.on('load', function (e) {
doSetClassAdobeTarget(e);
});
// タブをclickした時に実行
observer.on('gridviewchange', function (e) {
doSetClassAdobeTarget(e);
});
}
// AdobeTarget の同期的な実行
if (typeof adobe !== 'undefined') {
if (typeof adobe.target !== 'undefined') {
// adobe object が作られていても event がない場合がある模様なので undefined 対処
if (typeof adobe.target.event !== 'undefined') {
// Content Rendering Succeeded 時に取得できるカスタムイベントを利用して実行する
if (typeof adobe.target.event.CONTENT_RENDERING_SUCCEEDED !== 'undefined') {
document.addEventListener(adobe.target.event.CONTENT_RENDERING_SUCCEEDED, function () {
doSetAdobeAndPageExecution();
});
}
}
}
}
doSetAdobeAndPageExecution();
} );
$( function () {
// 小画面時、メニューを画面上部に追従
var $win = $( window );
var $el = $( '.home-Main__menu' );
var $inner = $el.find( '.home-Main__menuInner' );
var className = 'home-Main--floating';
if ( $el.length === 0 ) { return; }
$win.on( 'resize', _.throttle( setFloating, 200 ) );
$win.on( 'scroll', _.throttle( function () {
if ( /(base|large)/.test( s5.getCurrentScreenType() ) ) {
return;
}
setFloating();
}, 30 ) );
function setFloating () {
var scrollTop = $win.scrollTop();
var offsetTop = $el.offset().top;
if( scrollTop >= offsetTop && !$el.hasClass( className ) ) {
$el.addClass( className );
updateHeight();
} else if ( scrollTop < offsetTop && $el.hasClass( className ) ) {
$el.removeClass( className );
updateHeight();
}
}
function updateHeight () {
var isFloating = $el.hasClass( className );
if ( isFloating ) {
$el.css( { minHeight: $inner.height() } );
} else {
$el.removeAttr( 'style' );
}
}
} );
$(function () {
// signout 時のみ表示するエリアの要素削除処理
// ssflに頼るので ssfl を探してサインイン状態を取得し、
// サインインならば要素を削除
var ssflReady = function () {
var d = new $.Deferred();
var elapsed = 0;
// ssflが見つかるまで、200ms毎に判定
(function loop() {
if (!window.ssfl && elapsed < 30000) {
elapsed += 200;
setTimeout(loop, 200);
return;
} else {
d.resolve();
return;
}
})();
return d;
};
$.when(
ssflReady()
)
.done(
function () {
ssfl.userModel.on('change', function () {
if (ssfl.userModel.get('isLoggedIn')) {
$('[data-ssfl-view="signout"]').remove();
}
});
}
);
});
} )();