diff --git a/client/app/css/teambuilder.styl b/client/app/css/teambuilder.styl index bc3c51eb..83f3298e 100644 --- a/client/app/css/teambuilder.styl +++ b/client/app/css/teambuilder.styl @@ -256,6 +256,15 @@ $pokemon-list-height = 50px .hidden-power float right + .ev-lock + float left + margin-right 5px + cursor pointer + .icon-lock + color #444 + .icon-unlocked + color #888 + .remaining-evs-amount.over-limit color $negative-color font-weight bold @@ -313,9 +322,8 @@ $pokemon-list-height = 50px opacity .8 font-weight bold -.teambuilder .table-moves +.table-moves border-collapse separate - margin-top 8px border solid 1px #DDD thead th background whitesmoke @@ -328,8 +336,17 @@ $pokemon-list-height = 50px background #f0f0f9 &:first-child text-decoration underline + &.selected td + background #f0f0f9 + &:first-child + font-weight bold img margin-bottom 3px + .name + white-space nowrap + +.teambuilder .table-moves + margin-top 8px .teambuilder .display_teams position absolute diff --git a/client/app/js/helpers/challenge_pane.coffee b/client/app/js/helpers/challenge_pane.coffee index 3cb7ad2e..dd40cbae 100644 --- a/client/app/js/helpers/challenge_pane.coffee +++ b/client/app/js/helpers/challenge_pane.coffee @@ -67,17 +67,20 @@ $wrapper.html(JST['new_battle']({window, defaultClauses})) $selectFormat = $wrapper.find(".select-format") + # Implement finding battle/challenging $button.on 'click.challenge', -> # Start requesting for notify permission here PokeBattle.requestNotifyPermission() format = $selectFormat.data('format') + # Toggle state when you press the button. if !$button.hasClass('disabled') team = getSelectedTeam() unless team alert("You need to create a team using the Teambuilder before you can battle.") + PokeBattle.navigation.showTeambuilder() return disableButtons() @@ -100,6 +103,7 @@ team = getSelectedTeam() unless team alert("You need to create a team using the Teambuilder before you can battle.") + PokeBattle.navigation.showTeambuilder() return disableButtons() teamJSON = team.toNonNullJSON().pokemon @@ -136,10 +140,9 @@ # Clicking the team dropdown brings down a team selection menu. # Also updates the allTeams collection $wrapper.find('.select-team').click (e) -> - allTeams = PokeBattle.TeamStore.models - if allTeams && allTeams.length > 0 - html = JST['team_dropdown'](window: window, teams: allTeams) - $wrapper.find('.team-dropdown').html(html) + allTeams = PokeBattle.TeamStore.models || [] + html = JST['team_dropdown'](window: window, teams: allTeams) + $wrapper.find('.team-dropdown').html(html) # Selecting a team from the menu $wrapper.find('.team-dropdown').on 'click', '.select-team-dropdown-item', (e) -> @@ -147,6 +150,10 @@ selectedTeamId = PokeBattle.TeamStore.at(slot).id renderCurrentTeam($wrapper) + # Selecting build team from the menu + $wrapper.find('.team-dropdown').on 'click', '.build-team-option', (e) -> + PokeBattle.navigation.showTeambuilder() + # Selecting the format changes the dropdown. $wrapper.find('.format-dropdown').on 'click', '.select-format-dropdown-item', (e) -> $target = $(e.currentTarget) diff --git a/client/app/js/models/battles/pokemon.coffee b/client/app/js/models/battles/pokemon.coffee index 8e1ce503..8118ac43 100644 --- a/client/app/js/models/battles/pokemon.coffee +++ b/client/app/js/models/battles/pokemon.coffee @@ -100,6 +100,10 @@ class @Pokemon extends Backbone.Model getSelectableFormes: -> _(@getFormes()).reject((forme) => @getForme(forme).isBattleOnly) + # Returns all mega formes + getMegaFormes: -> + _(@getFormes()).reject((forme) => forme.indexOf('mega') != 0) + getAbilities: -> forme = @getForme() abilities = _.clone(forme.abilities) @@ -120,6 +124,9 @@ class @Pokemon extends Backbone.Model genders.push("M", "F") genders + hasSelectedMove: (moveName) -> + moveName && moveName in @moves + getMovepool: -> {SpeciesData, MoveData} = @getGeneration() generation = GENERATION_TO_INT[@collection?.generation || DEFAULT_GENERATION] @@ -230,12 +237,21 @@ class @Pokemon extends Backbone.Model "Healthy" canMegaEvolve: -> + # TODO: Refactor this to use getPossibleMegaForme() + # I didn't feel like making the change and testing it while implementing getPossibleMegaForme() item = @getItem() return false if item.type != 'megastone' [ species, forme ] = item.mega return false if @get('species') != species || @get('forme') != 'default' return true + getPossibleMegaForme: -> + item = @getItem() + return null if item?.type != 'megastone' + [ species, forme ] = item.mega + return forme if @get('species') == species && @get('forme') == 'default' + return null + # Returns the complete web address to the pokedex link for this pokemon. # For this project, this leads to our website at http://www.pokebattle.com, # but if you want it to lead somewhere else, edit this function. diff --git a/client/app/js/views/teambuilder/pokemon_edit_view.coffee b/client/app/js/views/teambuilder/pokemon_edit_view.coffee index 3ad8d595..da7e92db 100644 --- a/client/app/js/views/teambuilder/pokemon_edit_view.coffee +++ b/client/app/js/views/teambuilder/pokemon_edit_view.coffee @@ -33,6 +33,7 @@ class @PokemonEditView extends Backbone.View 'click .selected_shininess': 'changeShiny' 'click .selected_happiness': 'changeHappiness' 'change .selected-forme': 'changeForme' + 'change .selected-mega': 'changeMega' 'change .selected_nature': 'changeNature' 'change .selected_ability': 'changeAbility' 'change .selected_item': 'changeItem' @@ -42,7 +43,9 @@ class @PokemonEditView extends Backbone.View 'focus .ev-entry': 'focusEv' 'blur .ev-entry': 'changeEv' 'change .ev-entry': 'changeEv' - 'input .ev-entry[type=range]': 'changeEv' # fix for firefox + 'input .ev-entry[type=range]': 'changeEv' + 'mouseup .ev-entry[type=range]': 'mouseupEVSlider' + 'click .ev-lock': 'toggleEVLocked' 'change .select-hidden-power': 'changeHiddenPower' 'keydown .selected_moves input': 'keydownMoves' 'blur .selected_moves input': 'blurMoves' @@ -86,6 +89,13 @@ class @PokemonEditView extends Backbone.View setTeamPBV: (pbv) => @teamPBV = pbv + # Returns true if Evs are locked to 510 maximum + isEVLocked: => + $('.ev-lock span:visible').data('locked') + + toggleEVLocked: => + $('.ev-lock span').toggle() + changeSpecies: (e) => return if not @onPokemonChange species = $(e.currentTarget).val() @@ -114,6 +124,23 @@ class @PokemonEditView extends Backbone.View # Forme changes may have different abilities, so we have to change this. @pokemon.set('ability', @pokemon.getAbilities()[0]) + changeMega: (e) => + mega = $(e.currentTarget).val() + if mega + for itemName, data of @generation.ItemData + if data.mega && data.mega[0] == @pokemon.get('species') && data.mega[1] == mega + @pokemon.set('item', itemName) + console.log(itemName) + break + else + # Converting to non-mega. Remove the megastone if any + item = @generation.ItemData[@pokemon.get('item')] + if item?.mega?[0] == @pokemon.get('species') + @pokemon.set('item', null) + + # update the item dropdown (note: somewhat inefficient as it updates multiple dropdowns) + @renderNonStats() + changeNature: (e) => $list = $(e.currentTarget) @pokemon.set("nature", $list.val()) @@ -155,16 +182,25 @@ class @PokemonEditView extends Backbone.View $input.val("") if value == 0 changeEv: (e) => - # todo: make changeIv and changeEv DRY $input = $(e.currentTarget) stat = $input.data("stat") value = parseInt($input.val(), 10) + value = 0 if isNaN(value) value = 252 if value > 252 - value = 0 if isNaN(value) || value < 0 + if @isEVLocked() + availableEVs = 510 - @pokemon.getTotalEVs(exclude: stat) + value = availableEVs if value > availableEVs + + value = 0 if value < 0 value = @pokemon.setEv(stat, value) $input.val(value) if not $input.is("[type=range]") + mouseupEVSlider: (e) => + $slider = $(e.currentTarget) + $input = @$(".ev-entry[data-stat=#{$slider.data('stat')}]").not($slider) + $slider.val $input.val() + changeHiddenPower: (e) => $input = $(e.currentTarget) type = $input.val() @@ -180,6 +216,8 @@ class @PokemonEditView extends Backbone.View blurMoves: (e) => $input = $(e.currentTarget) + + # If preventBlur is set, then perform a refocus (undo the blur) if @_preventBlur previousScrollPosition = @$el.scrollTop() $input.focus() @@ -192,7 +230,7 @@ class @PokemonEditView extends Backbone.View # Remove filtering and row selection @filterMovesBy("") - $(".table-moves .active").removeClass("active") + @$(".table-moves .active").removeClass("active") if $input.val().length == 0 @recordMoves() @@ -202,13 +240,19 @@ class @PokemonEditView extends Backbone.View clickMoveName: (e) => $this = $(e.currentTarget) moveName = $this.data('move-id') - $moves = @$el.find('.selected_moves') - $input = $moves.find('input:focus').first() - $input = $moves.find('input').first() if $input.length == 0 - return if $input.length == 0 - @insertMove($input, moveName) - insertMove: ($input, moveName) => + if moveName in @getSelectedMoves() + @removeMove(moveName) + else + @insertMove(moveName) + + insertMove: (moveName, $input) => + if !$input + $moves = @$el.find('.selected_moves') + $input = $moves.find('input:focus').first() + $input = $moves.find('input').first() if $input.length == 0 + return if $input.length == 0 + currentScrollPosition = @$el.scrollTop() @preventBlurMoves() @@ -220,16 +264,36 @@ class @PokemonEditView extends Backbone.View @$el.scrollTop(currentScrollPosition) else @$el.scrollTop(0) + + @collapseSelectedMoves() @recordMoves() - recordMoves: => + removeMove: (moveName) => + indices = (i for move, i in @getAllSelectedMoves() when move == moveName) + + for idx in indices + $input = @$('.selected_moves .move-slot').eq(idx).children() + $input = @reverseButtonify($input) if $input.is('.move-button') + $input.val("") + + @collapseSelectedMoves() + + # Returns the moves currently selected in the teambuilder (Not the Pokemon) + getSelectedMoves: => + _(@getAllSelectedMoves()).compact() + + # Returns the contents of each selected move, even if that selected move is null + # Non-buttonified moves are considered null + getAllSelectedMoves: => movesArray = [] - $moves = @$el.find('.selected_moves') - $moves.find('.move-button').each -> - moveName = $(this).find("span").text().trim() - if moveName != "" - movesArray.push(moveName) - @pokemon.set("moves", movesArray) + $moves = @$el.find('.selected_moves .move-slot') + $moves.each -> + moveName = $(this).find(".move-button span").text().trim() + movesArray.push(moveName) + movesArray + + recordMoves: => + @pokemon.set("moves", @getSelectedMoves()) $selectedMove: => $table = @$el.find('.table-moves') @@ -238,36 +302,51 @@ class @PokemonEditView extends Backbone.View clickSelectedMove: (e) => $this = $(e.currentTarget) - moveName = $this.find('span').text() - $input = $("") - $this.replaceWith($input) - $input.focus().select() + moveName = @reverseButtonify($this).focus().select().val() # Set the current move row to active $(".table-moves tr[data-move-id='#{moveName}']").addClass("active") removeSelectedMove: (e) => $this = $(e.currentTarget).parent() - $input = $("") - $this.replaceWith($input) - $input.focus() + @reverseButtonify($this).val('').focus() + + @collapseSelectedMoves() + + # Nothing selected? Focus something + if @$('.selected_moves input:focus').length == 0 + @$('.selected_moves input').first().focus() + e.stopPropagation() buttonify: ($input, moveName) => return false if moveName not of @moveData - # The blur event may have been cancelled, so when removing the input also - # remove the filter + # When removing the input also remove the filter + # Normally this is done by blurMoves, + # but the blur event may have been prevented by preventBlurMoves if $input.is(":focus") @filterMovesBy("") - $(".table-moves .active").removeClass("active") + @$(".table-moves .active").removeClass("active") type = @moveData[moveName].type.toLowerCase() $input.replaceWith("""
""") + + @updateSelectedMoveStyles() + return true + reverseButtonify: ($buttons) => + $inputs = $buttons.replaceWith (i, element) => + $button = $(element) + moveName = $button.find('span').text() + $("") + + @updateSelectedMoveStyles() + $inputs + keydownMoves: (e) => $input = $(e.currentTarget) $table = @$el.find('.table-moves') @@ -275,7 +354,7 @@ class @PokemonEditView extends Backbone.View switch e.which when 13 # [Enter]; we're selecting the active move. $activeMove = @$selectedMove() - $activeMove.click() + @insertMove($activeMove.data('move-id')) when 38 # [Up arrow]; selects move above $activeMove = $allMoves.filter('.active').first() $prevMove = $activeMove.prevAll(":visible").first() @@ -445,3 +524,25 @@ class @PokemonEditView extends Backbone.View $this = $(el) moveName = $this.val() @buttonify($this, moveName) + + # Rerenders the list of selected moves without rerendering the entire moves table + collapseSelectedMoves: => + $selectedMoves = @$('.selected_moves') + + # First, check if an input is focused and empty. IF it is, we have to refocus + $focused = $selectedMoves.find('input:focus') + refocus = true if $focused.length != 0 && $focused.val() == '' + + $moveSlots = $selectedMoves.find('.move-slot') + $emptySlots = $moveSlots.filter -> + input = $(this).find('input') + input.length > 0 && input.val() == '' + + $selectedMoves.find('.row-fluid').append($emptySlots.detach()) + + $selectedMoves.find('input').first().focus() if refocus + + updateSelectedMoveStyles: => + @$(".table-moves .selected").removeClass("selected") + for move in @getSelectedMoves() + @$(".table-moves tr[data-move-id='#{move}']").addClass("selected") \ No newline at end of file diff --git a/client/vendor/css/icomoon.css b/client/vendor/css/icomoon.css index 86eb8f29..9080d390 100644 --- a/client/vendor/css/icomoon.css +++ b/client/vendor/css/icomoon.css @@ -1,12 +1,12 @@ @font-face { - font-family: 'icomoon'; - src:url('../fonts/icomoon.eot'); - src:url('../fonts/icomoon.eot?#iefix') format('embedded-opentype'), - url('../fonts/icomoon.ttf') format('truetype'), - url('../fonts/icomoon.woff') format('woff'), - url('../fonts/icomoon.svg#icomoon') format('svg'); - font-weight: normal; - font-style: normal; + font-family: 'icomoon'; + src:url('../fonts/icomoon.eot?-lv7lfm'); + src:url('../fonts/icomoon.eot?#iefix-lv7lfm') format('embedded-opentype'), + url('../fonts/icomoon.woff?-lv7lfm') format('woff'), + url('../fonts/icomoon.ttf?-lv7lfm') format('truetype'), + url('../fonts/icomoon.svg?-lv7lfm#icomoon') format('svg'); + font-weight: normal; + font-style: normal; } [class^="icon-"], [class*=" icon-"] { @@ -24,6 +24,12 @@ -moz-osx-font-smoothing: grayscale; } +.icon-lock:before { + content: "\e60e"; +} +.icon-unlocked:before { + content: "\e60f"; +} .icon-home:before { content: "\e600"; } diff --git a/client/views/team_dropdown.jade b/client/views/team_dropdown.jade index 54815db9..939d00ad 100644 --- a/client/views/team_dropdown.jade +++ b/client/views/team_dropdown.jade @@ -1,9 +1,11 @@ -if teams +if team + div= team.getName() + != window.JST['team_small']({team: team, window: window}) +else each team, i in teams li a.select-team-dropdown-item(data-slot = i) div= team.getName() != window.JST['team_small']({team: team, window: window}) -else - div= team.getName() - != window.JST['team_small']({team: team, window: window}) + li + a.build-team-option Build a Team diff --git a/client/views/teambuilder/moves.jade b/client/views/teambuilder/moves.jade index 4f7df0a0..19e575f6 100644 --- a/client/views/teambuilder/moves.jade +++ b/client/views/teambuilder/moves.jade @@ -5,13 +5,13 @@ ="View " + pokemon.get('species') + " Movesets" .row-fluid - .span3 + .span3.move-slot input(type="text", value=pokemon.get("moves")[0]) - .span3 + .span3.move-slot input(type="text", value=pokemon.get("moves")[1]) - .span3 + .span3.move-slot input(type="text", value=pokemon.get("moves")[2]) - .span3 + .span3.move-slot input(type="text", value=pokemon.get("moves")[3]) table.table.table-hover.table-moves @@ -27,7 +27,7 @@ table.table.table-hover.table-moves tbody each move in pokemon.getMovepool() tr(data-move-id=move.name, data-move-search-id=move.name.replace(/\s+|-/g, "")) - td= move.name + td.name= move.name td img(src=window.TypeSprite(move.type), alt=move.type) td @@ -36,4 +36,4 @@ table.table.table-hover.table-moves td= (move.power == 0) ? "-" : move.power td.acc= (move.accuracy == 0) ? "-" : move.accuracy + '%' td.pp= move.pp - td.description Description will go here + td.description= move.description diff --git a/client/views/teambuilder/pokemon.jade b/client/views/teambuilder/pokemon.jade index 976d9ce2..364fe4b7 100644 --- a/client/views/teambuilder/pokemon.jade +++ b/client/views/teambuilder/pokemon.jade @@ -77,6 +77,9 @@ mixin printStat(statName, keyName) td td(colspan="5") .remaining-evs + .ev-lock + span(data-locked='true').icon-lock + span(data-locked='false').icon-unlocked.hidden | Remaining EVs: span.remaining-evs-amount .hidden-power diff --git a/client/views/teambuilder/species.jade b/client/views/teambuilder/species.jade index a29497f2..d8298c8b 100644 --- a/client/views/teambuilder/species.jade +++ b/client/views/teambuilder/species.jade @@ -18,3 +18,14 @@ if formes.length > 1 - var displayedForme = forme[0].toUpperCase() + forme.substr(1) - var selected = (forme === pokemon.get('forme')) option(value=forme, selected=selected)= displayedForme + +- var megaFormes = pokemon.getMegaFormes() +if megaFormes.length > 0 + .teambuilder_row + .teambuilder_col Mega Forme: + select.teambuilder_col.selected-mega + option(value="", selected=(pokemon.getPossibleMegaForme() == null)) None + each forme in megaFormes + - var displayedForme = forme[0].toUpperCase() + forme.substr(1) + - var selected = (forme === pokemon.getPossibleMegaForme()) + option(value=forme, selected=selected)= displayedForme \ No newline at end of file diff --git a/icomoon-selection.json b/icomoon-selection.json index 2ffb9fb5..385d1928 100644 --- a/icomoon-selection.json +++ b/icomoon-selection.json @@ -1,6 +1,52 @@ { "IcoMoonType": "selection", "icons": [ + { + "icon": { + "paths": [ + "M592 448h-16v-192c0-105.87-86.13-192-192-192h-128c-105.87 0-192 86.13-192 192v192h-16c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48zM384 896h-128l27.84-139.2c-16.808-11.532-27.84-30.874-27.84-52.8 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 21.926-11.032 41.268-27.84 52.8l27.84 139.2zM448 448h-256v-192c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192z" + ], + "tags": [ + "lock", + "secure", + "private", + "encrypted" + ], + "grid": 16 + }, + "properties": { + "id": 137, + "order": 2, + "prevSize": 32, + "code": 58894, + "name": "lock", + "ligatures": "" + }, + "setIdx": 0, + "iconIdx": 137 + }, + { + "icon": { + "paths": [ + "M768 64h-128c-105.87 0-192 86.13-192 192v192h-400c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48h-16v-192c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192h128v-192c0-105.87-86.13-192-192-192zM384 896h-128l27.84-139.2c-16.808-11.532-27.84-30.874-27.84-52.8 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 21.926-11.032 41.268-27.84 52.8l27.84 139.2z" + ], + "tags": [ + "unlocked", + "lock" + ], + "grid": 16 + }, + "properties": { + "id": 138, + "order": 1, + "prevSize": 32, + "code": 58895, + "name": "unlocked", + "ligatures": "" + }, + "setIdx": 0, + "iconIdx": 138 + }, { "icon": { "paths": [ @@ -400,42 +446,22 @@ "name": "icomoon" }, "preferences": { + "showGlyphs": true, + "showQuickUse": true, "fontPref": { "prefix": "icon-", "metadata": { "fontFamily": "icomoon" }, - "showGlyphs": true, "metrics": { - "emSize": 1024, + "emSize": 512, "baseline": 6.25, "whitespace": 50 - }, - "resetPoint": 58880, - "showQuickUse": true, - "quickUsageToken": false, - "showMetrics": true, - "showMetadata": false, - "autoHost": true - }, - "imagePref": { - "color": 0, - "height": 32, - "columns": 16, - "margin": 16, - "png": false, - "sprites": true + } }, + "imagePref": {}, "historySize": 100, "showCodes": true, - "gridSize": 16, - "showLiga": false, - "showGrid": true, - "showGlyphs": true, - "showQuickUse": true, - "search": "", - "quickUsageToken": { - "UntitledProject1": "NDU4Yzk3NTA5NzFlOTk2YzgyMDViMDY1ZTlkM2FhNjcjMiMxNDAwNTgyMTM2IyMj" - } + "search": "" } } \ No newline at end of file diff --git a/public/fonts/icomoon.eot b/public/fonts/icomoon.eot index 14a147ef..c1cf462a 100644 Binary files a/public/fonts/icomoon.eot and b/public/fonts/icomoon.eot differ diff --git a/public/fonts/icomoon.svg b/public/fonts/icomoon.svg index b85c686f..a152b8a4 100644 --- a/public/fonts/icomoon.svg +++ b/public/fonts/icomoon.svg @@ -3,24 +3,26 @@ \ No newline at end of file diff --git a/public/fonts/icomoon.ttf b/public/fonts/icomoon.ttf index c66977a2..d894544c 100644 Binary files a/public/fonts/icomoon.ttf and b/public/fonts/icomoon.ttf differ diff --git a/public/fonts/icomoon.woff b/public/fonts/icomoon.woff index 58b88033..d43499ec 100644 Binary files a/public/fonts/icomoon.woff and b/public/fonts/icomoon.woff differ