isMobileOrAndroid = -> return true if /Mobile/i.test(window.navigator.userAgent) return true if /Android/i.test(window.navigator.userAgent) return false # helper which attaches selectize attachSelectize = ($element, options) -> # Block selectize on mobile and all android operating systems (All androids are blocked due to a bug) return if isMobileOrAndroid() $element.selectize(options) setSelectizeValue = ($element, value) -> if isMobileOrAndroid() $element.val(value) else $element.each -> @selectize?.setValue(value) setSelectizeDisabled = ($element, disabled) -> $element.filter(".selectized").each -> return unless @selectize if disabled then @selectize.disable() else @selectize.enable() class @PokemonEditView extends Backbone.View editTemplate: JST['teambuilder/pokemon'] speciesTemplate: JST['teambuilder/species'] nonStatsTemplate: JST['teambuilder/non_stats'] movesTemplate: JST['teambuilder/moves'] events: 'change .sortSpecies': 'changeSort' 'change .species_list': 'changeSpecies' 'change .selected_nickname': 'changeNickname' 'click .selected_shininess': 'changeShiny' 'click .selected_happiness': 'changeHappiness' 'change .selected-forme': 'changeForme' 'change .selected_nature': 'changeNature' 'change .selected_ability': 'changeAbility' 'change .selected_item': 'changeItem' 'change .selected_gender': 'changeGender' 'change .selected_level': 'changeLevel' 'change .iv-entry': 'changeIv' 'focus .ev-entry': 'focusEv' 'blur .ev-entry': 'changeEv' 'change .ev-entry': 'changeEv' 'input .ev-entry[type=range]': 'changeEv' # fix for firefox 'change .select-hidden-power': 'changeHiddenPower' 'keydown .selected_moves input': 'keydownMoves' 'blur .selected_moves input': 'blurMoves' 'click .table-moves tbody tr': 'clickMoveName' 'mousedown .table-moves': 'preventBlurMoves' 'click .move-button': 'clickSelectedMove' 'click .move-button .close': 'removeSelectedMove' initialize: (attributes={}) => @onPokemonChange = attributes.onPokemonChange setFormat: (format) => format = Formats[format] || Formats[DEFAULT_FORMAT] @setGeneration(format.generation) # TODO: Set PBV limit based on conditions changeSort:(e) => sort = $(e.currentTarget).val() console.log(sort) if sort =="Default Sort" @sortSpecieslist("Default") else if sort == "Sort by Dexnumber" @sortSpecieslist("id", false) else if sort == "Invert by Dexnumber" @sortSpecieslist("id", true) else if sort == "Sort Alphabetically" @sortSpecieslist("pokename", false) else if sort == "Invert Alphabetically" @sortSpecieslist("pokename", true) sortSpecieslist: (option, reverse) => {MoveData, SpeciesData, ItemData} = @generation if option == "Default" sortedlist = @getSpecies else sortedlist = @sortObject(SpeciesData, option, reverse) @speciesList = (species for species, data of sortedlist) @render() sortObject: (data, option, reverse) -> arr = [] for key, val of data val.pokename = key arr.push(val) arr = _.sortBy(arr, option) if reverse == true arr.reverse() newobj = {} for thing in arr newobj[thing.pokename] = thing finished = newobj setGeneration: (generation) => @generation = window.Generations[generation.toUpperCase()] {MoveData, SpeciesData, ItemData} = @generation @moveData = MoveData @speciesList = (species for species, data of SpeciesData) # TODO: filter irrelevant items @itemList = (_(itemName for itemName, data of ItemData).sort()) @render() setPokemon: (pokemon) => # Stop listening for change events on the previously set pokemon @stopListening(@pokemon) if @pokemon @pokemon = pokemon @listenTo(pokemon, 'change:level', @renderStats) @listenTo(pokemon, 'change:ivs', @renderStats) @listenTo(pokemon, 'change:evs', @renderStats) @listenTo(pokemon, 'change:nature', @renderStats) @listenTo(pokemon, 'change:hiddenPowerType', @renderStats) @listenTo(pokemon, 'change:shiny', @renderSpecies) @renderPokemon() setTeamPBV: (pbv) => @teamPBV = pbv changeSpecies: (e) => return if not @onPokemonChange species = $(e.currentTarget).val() @pokemon = if species new Pokemon(teambuilder: true, species: species) else new NullPokemon() @onPokemonChange(@pokemon) changeNickname: (e) => $input = $(e.currentTarget) @pokemon.set("name", $input.val()) changeShiny: (e) => $switch = $(e.currentTarget).toggleClass("selected") @pokemon.set("shiny", $switch.is(".selected")) changeHappiness: (e) => $switch = $(e.currentTarget).toggleClass("selected") happiness = if $switch.is(".selected") then 0 else 100 @pokemon.set("happiness", happiness) changeForme: (e) => $forme = $(e.currentTarget) @pokemon.set('forme', $forme.val()) # Forme changes may have different abilities, so we have to change this. @pokemon.set('ability', @pokemon.getAbilities()[0]) changeNature: (e) => $list = $(e.currentTarget) @pokemon.set("nature", $list.val()) changeAbility: (e) => $list = $(e.currentTarget) @pokemon.set("ability", $list.val()) changeItem: (e) => $list = $(e.currentTarget) @pokemon.set("item", $list.val()) changeGender: (e) => $list = $(e.currentTarget) @pokemon.set("gender", $list.val()) changeLevel: (e) => $input = $(e.currentTarget) value = parseInt($input.val(), 10) value = 1120 if isNaN(value) || value > 120 value = 1 if value < 1 $input.val(value) @pokemon.set("level", value) changeIv: (e) => # todo: make changeIv and changeEv DRY $input = $(e.currentTarget) stat = $input.data("stat") value = parseInt($input.val(), 10) if isNaN(value) || value > 31 || value < 0 value = 31 @pokemon.setIv(stat, value) focusEv: (e) => $input = $(e.currentTarget) return if $input.is("[type=range]") value = parseInt($input.val(), 10) $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 = 252 if value > 252 value = 0 if isNaN(value) || value < 0 value = @pokemon.setEv(stat, value) $input.val(value) if not $input.is("[type=range]") changeHiddenPower: (e) => $input = $(e.currentTarget) type = $input.val() @pokemon.set('hiddenPowerType', type.toLowerCase()) # Prevents the blurMoves event from activating for the duration of # the remaining javascript events. This allows the click event to not fire # the blur event. preventBlurMoves: (e) => @_preventBlur = true _.defer => @_preventBlur = false blurMoves: (e) => $input = $(e.currentTarget) if @_preventBlur previousScrollPosition = @$el.scrollTop() $input.focus() e.preventDefault() @$el.scrollTop(previousScrollPosition) # prevent scroll from refocus return $selectedMove = @$selectedMove() moveName = $selectedMove.data('move-id') # Remove filtering and row selection @filterMovesBy("") $(".table-moves .active").removeClass("active") if $input.val().length == 0 @recordMoves() else @insertMove($input, moveName) 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) => currentScrollPosition = @$el.scrollTop() @preventBlurMoves() return if !@buttonify($input, moveName) $moves = @$el.find('.selected_moves') $firstInput = $moves.find('input').first() if $firstInput.length > 0 $firstInput.focus() @$el.scrollTop(currentScrollPosition) else @$el.scrollTop(0) @recordMoves() recordMoves: => 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) $selectedMove: => $table = @$el.find('.table-moves') $allMoves = $table.find('tbody tr') $allMoves.filter('.active').first() clickSelectedMove: (e) => $this = $(e.currentTarget) moveName = $this.find('span').text() $input = $("") $this.replaceWith($input) $input.focus().select() # 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() 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 if $input.is(":focus") @filterMovesBy("") $(".table-moves .active").removeClass("active") type = @moveData[moveName].type.toLowerCase() $input.replaceWith("""
#{moveName}
×
""") return true keydownMoves: (e) => $input = $(e.currentTarget) $table = @$el.find('.table-moves') $allMoves = $table.find('tbody tr') switch e.which when 13 # [Enter]; we're selecting the active move. $activeMove = @$selectedMove() $activeMove.click() when 38 # [Up arrow]; selects move above $activeMove = $allMoves.filter('.active').first() $prevMove = $activeMove.prevAll(":visible").first() if $prevMove.length > 0 $activeMove.removeClass('active') $prevMove.addClass('active') when 40 # [Down arrow]; selects move below $activeMove = $allMoves.filter('.active').first() $nextMove = $activeMove.nextAll(":visible").first() if $nextMove.length > 0 $activeMove.removeClass('active') $nextMove.addClass('active') else # Otherwise we're filtering moves # We defer since $input may not have updated yet _.defer => return unless $input.is(":focus") moveName = $input.val() @filterMovesBy(moveName) filterMovesBy: (moveName) => moveName = moveName.replace(/\s+|-/g, "") $table = @$el.find('.table-moves') $allMoves = $table.find('tbody tr') moveRegex = new RegExp(moveName, "i") $moves = $allMoves.filter -> $move = $(this) moveName = $move.data('move-search-id') moveRegex.test(moveName) $table.addClass('hidden') $moves.removeClass('hidden') $allMoves.not($moves).addClass('hidden') $allMoves.removeClass('active') $moves.first().addClass('active') $table.removeClass('hidden') disableEventsAndExecute: (callback) => isOutermost = !@_eventsDisabled @_eventsDisabled = true @undelegateEvents() if isOutermost # disable events callback() @delegateEvents() if isOutermost @_eventsDisabled = false if isOutermost render: => @$el.html @editTemplate(window: window, speciesList: @speciesList, itemList: @itemList) attachSelectize(@$el.find(".species_list"), render: option: (item, escape) => pbv = PokeBattle.PBV.determinePBV(@generation, species: item.value) return "
#{item.text}
#{pbv}
" ) attachSelectize(@$el.find(".selected_item")) return this renderPokemon: => @renderSpecies() @renderNonStats() @renderStats() @renderMoves() @renderPBV() # Disable entering values if this is a NullPokemon $elements = @$el.find("input, select").not(".species input, .species select") $elements.prop("disabled", @pokemon.isNull) setSelectizeDisabled($elements, @pokemon.isNull) return this renderPBV: => individualPBV = @pokemon.getPBV() @$(".individual-pbv").text(individualPBV) team = @pokemon.getTeam() if team && team.hasPBV() pbv = team.getPBV() maxPBV = team.getMaxPBV() @$(".total-pbv").text(pbv).toggleClass("red", pbv > maxPBV) @$(".max-pbv").text(maxPBV) renderSpecies: => @disableEventsAndExecute => setSelectizeValue(@$(".species_list"), @pokemon.get("species")) html = if @pokemon.isNull then "" else @speciesTemplate(window: window, pokemon: @pokemon) @$(".species-info").html(html) @$(".selected_shininess").toggleClass("selected", @pokemon.get('shiny') == true) @$(".selected_happiness").toggleClass("selected", @pokemon.get("happiness") == 0) renderNonStats: => $nonStats = @$el.find(".non-stats") populateSelect = (searchStr, valueTextPairs, selectedValue) -> $select = $nonStats.find(searchStr).empty() for pair in valueTextPairs value = text = pair if pair instanceof Array value = pair[0] text = pair[1] $select.append($("