Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #34210 from rexboy7/folder-picker
Browse files Browse the repository at this point in the history
Bug 1256261 - [TV][Home] Add and modify new folder through grid-view. r=lchang
  • Loading branch information
rexboy7 committed Apr 6, 2016
2 parents 51d7f6e + 7694419 commit 4c5c77a
Show file tree
Hide file tree
Showing 11 changed files with 603 additions and 209 deletions.
5 changes: 3 additions & 2 deletions shared/js/smart-screen/card_manager.js
Expand Up @@ -414,7 +414,7 @@

if (typeof options.index === 'number') {
position = options.index;
} else if (!newCard.group) {
} else if (!newCard.group || options.position === 'end') {
position = this._cardList.length;
} else {
// If the given card belongs to a deck (has type), we assume the deck
Expand Down Expand Up @@ -443,7 +443,8 @@

this._cardList.splice(position, 0, newCard);
this.writeCardlistInCardStore().then(function() {
that.fire('card-inserted', newCard, position, options.overFolder);
that.fire('card-inserted',
newCard, position, options.overFolder, options.silent);
});
}, this);
},
Expand Down
4 changes: 2 additions & 2 deletions shared/js/smart-screen/cards/folder.js
Expand Up @@ -171,15 +171,15 @@
this.fire('folder-changed', this);
};

Folder.prototype.addCard = function folder_addCard(card, index) {
Folder.prototype.addCard = function folder_addCard(card, index, options) {
// We don't support folder in folder
if (!this._isInFolder(card) && !(card instanceof Folder)) {
if (typeof index !== 'number') {
index = this._cardsInFolder.length;
}
this._cardsInFolder.splice(index, 0, card);
this._setDirty();
this.fire('card-inserted', card, index);
this.fire('card-inserted', card, index, null, options && options.silent);
}
};

Expand Down
18 changes: 18 additions & 0 deletions shared/js/smart-screen/key_navigation_adapter.js
Expand Up @@ -34,6 +34,7 @@
this._evtNames.forEach(
name => this._targetElement.addEventListener(name, this));

this.propagateKeyEvent = options.propagateKeyEvent || false;
},
uninit: function kna_uninit() {
this._evtNames.foreach(
Expand All @@ -44,6 +45,23 @@
if(this._evtNames.indexOf(evt.type) !== -1) {
this.handleKeyEvent(this.convertKeyToString(evt.keyCode), evt.type);
}

switch(evt.type) {
case 'keyup':
case 'keydown':
case 'keypress':
// By default we stop propagating keyevent. This is useful when we
// apply KeyNavigationAdapter to a blocked sub-component such as a
// modal-dialog-like UI. It prevents underlying UI act to the same
// key.
!this.propagateKeyEvent && evt.stopPropagation();
break;
case 'click':
// Do forced focus again on mouse click to prevent focus lost problem
// when running on devices like PC and phone.
this.focus();
break;
}
},

handleKeyEvent: function kna_handleKeyEvent(key, eventType) {
Expand Down
7 changes: 5 additions & 2 deletions shared/js/smart-screen/scrollable.js
Expand Up @@ -459,7 +459,7 @@
}
},

insertNodeBefore: function(newNode, startNode) {
insertNodeBefore: function(newNode, startNode, options) {
if (typeof startNode === 'number') {
startNode = this.nodes[startNode];
}
Expand All @@ -480,8 +480,11 @@
this.realignToReferenceElement();
this._shiftNodesPosition(1, newIdx);
}
this._slide(this.getItemFromNode(newNode), newIdx);
if (options && options.silent) {
return true;
}

this._slide(this.getItemFromNode(newNode), newIdx);
return true;
},

Expand Down
22 changes: 21 additions & 1 deletion tv_apps/smart-home/index.html
Expand Up @@ -22,6 +22,7 @@
<link rel="stylesheet" type="text/css" href="style/info-bar.css">
<link rel="stylesheet" type="text/css" href="style/search-bar.css">
<link rel="stylesheet" type="text/css" href="style/fte.css">
<link rel="stylesheet" type="text/css" href="style/card-picker.css">

<!-- default cards for first time launch -->
<link rel="resource" type="application/json" href="shared/resources/default-cards.json">
Expand Down Expand Up @@ -69,6 +70,8 @@
<script defer src="js/message_handler.js"></script>
<script defer src="js/edit.js"></script>
<script defer src="js/search_bar.js"></script>
<script defer src="js/card_picker.js"></script>
<script defer src="js/card_util.js"></script>

<script defer src="js/home.js"></script>
<script defer src="js/bootstrap.js"></script>
Expand All @@ -83,7 +86,7 @@
</head>

<body>
<article tabIndex="-1" role="region" class="skin-dark" id="main-section">
<article tabIndex="-1" role="region" class="skin-dark" id="main-section" contextmenu="card-menu">
<section id="background" class="background"></section>
<nav id="nav-regular">
<section id="header-buttons" class="left-top-panel">
Expand All @@ -94,6 +97,9 @@
<smart-button type="text-and-icon" id="settings-button" class="settings-button">
<span data-l10n-id="settings">settings</span>
</smart-button>
<smart-button type="text-and-icon" id="add-folder-button" class="add-folder-button">
<span data-l10n-id="add-folder">add folder</span>
</smart-button>
</section>
<section id="information-bar" class="information-bar">
<div id="clock-info" class="clock-info"><span id="time" class="time"></span></div>
Expand Down Expand Up @@ -137,6 +143,10 @@
</div>
</div>
</section>
<menu type="context" id="card-menu">
<menuitem icon="style/icons/ic_pin.png" data-l10n-id="edit-folder" id="edit-folder"></menuitem>
<menuitem icon="style/icons/ic_delete.png" data-l10n-id="remove-card" id="remove-card"></menuitem>
</menu>
<section id="filter-tab-container" class="filter-tab-container">
<div data-icon="filter" id="filter-tab-group" class="filter-tab-group">
<smart-button type="simple-text" id="filter-all-button" data-icon-type="filter">
Expand Down Expand Up @@ -188,6 +198,16 @@
</section>
</section>
</section>

<section id="card-picker" class="hidden">
<div id="card-picker-grid-view">
</div>
<section class="card-picker-panel">
<smart-button type="text-and-icon" id="hide-cardpicker-button" class="hide-cardpicker-button">
<span data-l10n-id="hide-cardpicker">Hide cardpicker</span>
</smart-button>
</section>
</section>
</article>
</body>

Expand Down
212 changes: 212 additions & 0 deletions tv_apps/smart-home/js/card_picker.js
@@ -0,0 +1,212 @@
/* global evt, KeyNavigationAdapter, SpatialNavigator, Folder, Deck,
CardUtil */

(function(exports) {
'use strict';

function CardPicker() {}

CardPicker.prototype = evt({
container: document.getElementById('card-picker'),
gridView: document.getElementById('card-picker-grid-view'),

hideCardPickerButton: document.getElementById('hide-cardpicker-button'),

init: function(options) {
this.appButtons = [];

this._cardManager = options.cardManager;
this._folder = null;

this.navigableElements = [
CardPicker.prototype.hideCardPickerButton
];

this.container.addEventListener('click', this.focus.bind(this));

this._spatialNavigator = new SpatialNavigator(this.navigableElements);
this._spatialNavigator.on('focus', this.onFocus.bind(this));
this._spatialNavigator.focus();

this.hideCardPickerButton.addEventListener('click', this.hide.bind(this));

this._keyNavigationAdapter = new KeyNavigationAdapter();
this._keyNavigationAdapter.init(this.container);
this._keyNavigationAdapter.on('move', direction => {
this._spatialNavigator.move(direction);
});
this._keyNavigationAdapter.on('enter-keyup', this.onEnter.bind(this));

this._selectedElements = this.gridView.getElementsByClassName('selected');

this.refresh();
},

onFocus: function(elem) {
elem.focus();
if (elem.classList.contains('app-button')) {
this._scrollTo(elem);
}
},

onEnter: function() {
var elem = this._spatialNavigator.getFocusedElement();
if (elem.classList.contains('app-button')) {
elem.classList.toggle('selected');
}
},

show: function(folderElem) {
this._mode = folderElem ? 'update' : 'add';
this._folder = null;
this.refresh(folderElem);
this.container.classList.remove('hidden');
this.focus();
},

hide: function() {
this.container.classList.add('hidden');
this.fire('hide');
},

refresh: function(folderElem) {
var folderList = null;
if (folderElem) {
this._folder = this._cardManager.findCardFromCardList({
cardId: folderElem.dataset.cardId
});
folderList = this._folder.getCardList();
}

this._cardManager.getCardList()
.then(cardList => {
this._refreshCardButtons(folderList, cardList);
this._spatialNavigator.setCollection(
this.appButtons.concat(this.navigableElements));
this._spatialNavigator.focus(this.appButtons[0]);
});
},

focus: function() {
this._spatialNavigator.focus();
},

_scrollTo: function(elem) {
var scrollY = (elem.offsetTop - this.gridView.offsetTop) -
(this.gridView.offsetHeight - elem.offsetHeight) / 2;
this.gridView.scrollTo(0, scrollY);
},

_refreshCardButtons: function(folderList, cardList, options) {
this.appButtons = [];
this.gridView.innerHTML = '';

var that = this;
function createButtonHelper(card) {
if(card instanceof Folder || card instanceof Deck) {
return;
}

var appButton = CardUtil.createCardButton(card);
that.gridView.appendChild(appButton);
that.appButtons.push(appButton);
return appButton;
}

folderList && folderList.forEach(card => {
var appButton = createButtonHelper(card);
if (appButton) {
appButton.dataset.parentType = 'folder';
appButton.classList.add('selected');
}
});

cardList && cardList.forEach(card => {
var appButton = createButtonHelper(card);
if (appButton) {
appButton.dataset.parentType = 'empty';
}
});
},

/**
* Functions for adding and updating to databases
*/

saveToNewFolder: function(position) {
if (this.selected.length <= 0) {
return;
}

this._folder = this._cardManager.insertNewFolder(
{id: 'new-folder'}, position);

this._saveToFolderHelper();
return this._folder;
},

updateFolder: function() {
if (!this._folder) {
return;
}
// Moves cards previously inside the folder back to cardList
this.appButtons.every(elem => {
// Buttons previously inside the folder are in the start of the array
// and we want to process them only.
if (elem.dataset.parentType !== 'folder') {
return false;
}
if (!elem.classList.contains('selected')) {
var card = this._folder.findCard({
cardId: elem.dataset.cardId
});
this._folder.removeCard(card);
this._cardManager.insertCard({
card: card,
position: 'end',
silent: true
});
}
return true;
});

// Then save newly added ones
this._saveToFolderHelper();
},

_saveToFolderHelper: function() {
if (!this._folder) {
return;
}

for (var i = 0; i < this.selected.length; i++) {
var button = this.selected[i];
if (button.dataset.parentType === 'folder') {
continue;
}

var card = this._cardManager.findCardFromCardList({
cardId: button.dataset.cardId
});
this._cardManager.removeCard(card);
this._folder.addCard(card, {silent: true});
}
},

/**
* Properties
*/
get isShown() {
return !this.container.classList.contains('hidden');
},

get selected() {
return this._selectedElements;
},

get mode() {
return this._mode;
}
});
exports.CardPicker = CardPicker;
}(window));

0 comments on commit 4c5c77a

Please sign in to comment.