class CardCollectionView extends View { constructor(element) { super(element); //Measure a dummy card. var measurementCard = new CardView(); measurementCard.element.style.left = "-100vw"; measurementCard.element.style.top = "-100vh"; measurementCard.element.style.position = "absolute"; document.body.appendChild(measurementCard.element); this.cardWidth = measurementCard.element.clientWidth; this.cardHeight = measurementCard.element.clientHeight; var style = window.getComputedStyle(measurementCard.element); var margin = parseInt(style.margin.replace("px", "")) * 2 * 2; this.cardWidth += margin; this.cardHeight += margin; document.body.removeChild(measurementCard.element); //Build the filter bar. this.filterBar = document.createElement("DIV"); this.filterBar.className = "filter-bar"; element.appendChild(this.filterBar); var projectLabel = document.createElement("LABEL"); projectLabel.setAttribute("for", "project-select"); projectLabel.innerText = "Project:"; this.filterBar.appendChild(projectLabel); this.projectSelect = document.createElement("SELECT"); this.projectSelect.id = "project-select"; this.projectSelect.addEventListener("change", this.applyFilters.bind(this)); this.filterBar.appendChild(this.projectSelect); var allProjects = document.createElement("OPTION"); allProjects.value = ""; allProjects.innerText = "(All)"; this.projectSelect.appendChild(allProjects); //Add category button. this.addCategoryButton = document.createElement("BUTTON"); this.addCategoryButton.className = "add-category-button require_w__card_category"; this.addCategoryButton.innerText = "Add Category"; this.addCategoryButton.addEventListener("click", this.onAddCategoryButtonPressed.bind(this)); this.filterBar.appendChild(this.addCategoryButton); //Add the listeners. OnTime.projectManager.addEventListener("projectadded", this.onProjectAdded.bind(this), true); OnTime.projectManager.addEventListener("projectremoved", this.onProjectRemoved.bind(this), true); OnTime.projectManager.addEventListener("projectchanged", this.onProjectChanged.bind(this), true); OnTime.cardManager.addEventListener("categoryadded", this.onCategoryAdded.bind(this)); OnTime.cardManager.addEventListener("categoryremoved", this.onCategoryRemoved.bind(this)); OnTime.cardManager.addEventListener("categorychanged", this.onCategoryChanged.bind(this)); OnTime.cardManager.addEventListener("cardadded", this.onCardAdded.bind(this)); OnTime.cardManager.addEventListener("cardremoved", this.onCardRemoved.bind(this)); OnTime.cardManager.addEventListener("cardchanged", this.onCardChanged.bind(this)); OnTime.cardManager.addEventListener("beforecardtransfer", this.beforeTransfer.bind(this)); OnTime.cardManager.addEventListener("aftercardtransfer", this.afterTransfer.bind(this)); OnTime.cardManager.addEventListener("cardtransfererror", this.onTransferError.bind(this)); this.categoryViews = { }; this.projectOptions = { }; } onProjectAdded(event) { var newProjectOption = document.createElement("OPTION"); newProjectOption.value = event.project.project_key; newProjectOption.innerText = event.project.name; if (event.project.description) { newProjectOption.title = event.project.description; } this.projectSelect.appendChild(newProjectOption); this.projectOptions[event.project.project_key] = newProjectOption; } onProjectRemoved(event) { if (!(event.project.project_key in this.projectOptions)) { console.error("Trying to remove a project option from a project select that does not exist in it."); return; } var option = this.projectOptions[event.project.project_key]; this.projectSelect.removeChild(option); delete this.projectOptions[event.project.project_key]; this.applyFilters(); } onProjectChanged(event) { if (!(event.project.project_key in this.projectOptions)) { console.error("Trying to change a project option in a project select that does not exist in it."); return; } var option = this.projectOptions[event.project.project_key]; option.innerText = event.project.name; option.title = event.project.description; } applyFilters() { var filterOptions = { }; if (this.projectSelect.value) { filterOptions["project_key"] = this.projectSelect.value; } for (var categoryKey in this.categoryViews) { this.categoryViews[categoryKey].setFilter(filterOptions); } } /** * Called after the card creation request returned successfully with a card key. * Adds the newly created card to it's destination category view. */ createCard(cardData) { if (!cardData.category_key in this.categoryViews) { console.error("Trying to add a card to a category that does not exist."); return; } OnTime.cardManager.addCard(cardData); } onCategoryAdded(event) { if (event.category.category_key in this.categoryViews) { console.error("A categoryadded event was called, but the category view already existed. This should not have happened."); return; } //alert("The category " + event.category.category_key + " was added!"); var cardCategoryView = new CardCategoryView(); cardCategoryView.setCategoryData({ category_key: event.category.category_key, name: event.category.name, icon: event.category.icon, cards: event.category.cards }); cardCategoryView.collectionView = this; cardCategoryView.viewController = this.viewController; this.element.appendChild(cardCategoryView.element); this.viewController.allSubviews.push(cardCategoryView); this.categoryViews[event.category.category_key] = cardCategoryView; } onCategoryRemoved(event) { if (!(event.category.category_key in this.categoryViews)) { console.error("A categoryremoved event was called, but there is no category view with this category key. This should not have happened."); return; } //alert("The category " + event.category.category_key + " was removed!"); var viewToRemove = this.categoryViews[event.category.category_key]; this.element.removeChild(viewToRemove.element); delete this.categoryViews[event.category.category_key]; } onCategoryChanged(event) { alert("The category " + event.category.category_key + " changed!"); this.applyFilters(); } onCardAdded(event) { if (!(event.card.category_key in this.categoryViews)) { console.error("Trying to add a card to a category without there being a category view with this key."); return; } //alert("The card " + event.card.card_key + " was added!"); this.categoryViews[event.card.category_key].addCard(event.card); this.applyFilters(); } onCardRemoved(event) { if (!(event.card.category_key in this.categoryViews)) { console.error("Trying to remove a card from a category without there being a category view with this key."); return; } //alert("The card " + event.card.card_key + " was removed!"); this.categoryViews[event.card.category_key].removeCard(event.card); } onCardChanged(event) { this.categoryViews[event.card.category_key].changeCard(event.card); //alert("The card " + event.card.card_key + " changed!"); this.applyFilters(); } /** * The event called before a card gets transferred. * Prepares both the source and the target category views as well as the card view itself. */ beforeTransfer(event) { if (!(event.sourceCategoryKey in this.categoryViews) || !(event.targetCategoryKey in this.categoryViews)) { //The category is not in this collection. Strange, but might happen at some point in the future. Let's just ignore it for now. return; } var sourceView = this.categoryViews[event.sourceCategoryKey]; var targetView = this.categoryViews[event.targetCategoryKey]; var transferringCardView = sourceView.prepareCardForTransfer(event.cardKey); if (!transferringCardView) { console.error("Trying to transfer a non-existant card view."); return; } this.transferringCardView = transferringCardView; } /** * The event called after a card was transferred successfully on the server. * Moves the card view to its new category view. */ afterTransfer(event) { if (!(event.sourceCategoryKey in this.categoryViews) || !(event.targetCategoryKey in this.categoryViews)) { //The category is not in this collection. Strange, but might happen at some point in the future. Let's just ignore it for now. return; } var sourceView = this.categoryViews[event.sourceCategoryKey]; var targetView = this.categoryViews[event.targetCategoryKey]; sourceView.removeCardAfterTransfer(event.cardKey); targetView.receiveCardTransfer(this.transferringCardView); //Transfer it in the collection itself and in the card manager. this.transferringCardView.transferToCategoryView(targetView); //Finish the transfer. targetView.hideDummy(); this.transferringCardView.reenable(); this.transferringCardView = null; } onTransferError(event) { if (!(event.sourceCategoryKey in this.categoryViews) || !(event.targetCategoryKey in this.categoryViews)) { //The category is not in this collection. Strange, but might happen at some point in the future. Let's just ignore it for now. return; } var targetView = this.categoryViews[event.targetCategoryKey]; targetView.hideDummy(); this.transferringCardView.reenable(); this.transferringCardView = null; } onAddCategoryButtonPressed(event) { UIKit.getPopoverById("add-category-popover").showForElement(event.currentTarget, "bottom"); event.stopPropagation(); } } UIKit.registerViewType(CardCollectionView);