context = window MIX_MODES = context.JK.MIX_MODES @JamTrackSearchScreen = React.createClass({ mixins: [Reflux.listenTo(@AppStore,"onAppInit"), Reflux.listenTo(@UserStore,"onUserChanged")] LIMIT: 10 instrument_logo_map: context.JK.getInstrumentIconMap24() input: null MAX_ARTIST_SHOW: 3 filterOption:() -> true render: () -> searchText = if @state.first_search then 'SEARCH' else 'SEARCH AGAIN' uiJamTracks = [] for jamtrack in @state.jamtracks trackRow = context._.clone(jamtrack) trackRow.track_cnt = jamtrack.tracks.length trackRow.tracks = [] # if an instrument is selected by the user, then re-order any jam tracks with a matching instrument to the top ###instrument = @instrument.val() if instrument? jamtrack.tracks.sort((a, b) => aWeight = @computeWeight(a, instrument) bWeight = @computeWeight(b, instrument) return aWeight - bWeight ) ### for track in jamtrack.tracks if track.track_type == 'Master' || track.track_type == 'Track' trackRow.tracks.push(track) if track.track_type == 'Master' track.instrument_desc = "Master" else if track.track_type == 'Track' inst = '../assets/content/icon_instrument_default24.png' if track.instrument? if track.instrument.id in @instrument_logo_map inst = @instrument_logo_map[track.instrument.id].asset track.instrument_desc = track.instrument.description track.instrument_url = inst if track.part != '' track.instrument_desc += ' (' + track.part + ')' trackRow.free_state = if (@state.is_free && jamtrack.allow_free) then 'free' else 'non-free' trackRow.is_free = @state.is_free && jamtrack.allow_free uiJamTracks.push trackRow artists = [] artistsShown = 0 for artist in @state.artists if @state.show_all_artists || artistsShown < @MAX_ARTIST_SHOW artists.push `
{artist.original_artist}
` artistsShown += 1 artists.push `
No matching artists
` if artists.length == 0 if !@state.show_all_artists && @state.artists.length > @MAX_ARTIST_SHOW artists.push `
show all
` else if @state.show_all_artists artists.push `
hide artists
` jamtracks = [] for jamtrack in uiJamTracks jamtrackPricesClasses = { "jamtrack-price" : true } jamtrackPricesClasses[jamtrack.free_state] = true jamtrackPricesClasses = classNames(jamtrackPricesClasses) tracks = [] for track in jamtrack.tracks tracks.push `
` actionBtn = null if jamtrack.purchased if jamtrack.can_download actionBtn = `PURCHASED` else priceNotice = `
$ {Number(jamtrack.upgrade_price).toFixed(2)}
` actionBtn = `
{priceNotice} UPGRADE TO FULL
HELP
` else if jamtrack.is_free actionBtn = `GET IT FREE!` else if jamtrack.added_cart actionBtn = `ALREADY IN CART` else priceNotice = `
$ {jamtrack.price}
` fullPriceNotice = `
$ {jamtrack.download_price}
` actionBtn = `
{priceNotice} ADD TO CART
{fullPriceNotice} ADD TO CART (FULL)
HELP
` availabilityNotice = null if jamtrack.sales_region==context.JK.AVAILABILITY_US availabilityNotice = `
This JamTrack available only to US customers.      why?
` jamtracks.push `
"{jamtrack.name}"
by {jamtrack.original_artist}

Songwriters:
{jamtrack.songwriter}
Publishers:
{jamtrack.publisher}
Genres:
{jamtrack.genres.join(', ')}
Version:
{jamtrack.recording_type}
show all tracks
{tracks}
{actionBtn} {availabilityNotice}
` #jamtracks.push `
No matching JamTracks
` if jamtracks.length == 0 searchClasses = classNames({ "button-orange" : true, "search-btn" : true, "disabled" : @state.searching }) artistSection = null jamTracksSection = null if @state.type == 'user-input' if @state.searching jamtracksHeader = "searching..." else jamtracksHeader = "search results: #{@state.count} jamtracks" else if @state.type == 'artist-select' jamtracksHeader = "search results: jamtracks for artist \"#{@state.artist}\"" else if @state.type == 'song-select' jamtracksHeader = "search results: jamtrack \"#{@state.song}\"" else throw "unknown search type #{@state.type}" if !@state.first_search # only show the artists links if the user typed the results if @state.type == 'user-input' artistSection = `

search results: artists

{artists}
` jamTracksSection = `

{jamtracksHeader} back to jamtracks home

{jamtracks}
JAMTRACK TRACKS INCLUDED / PREVIEW SHOP
No more JamTracks
` options = {} searchValue = if @state.search == 'SEPARATOR' then '' else window.JamTrackSearchInput `
Download JamTracks catalog
or
{artistSection} {jamTracksSection}
` clearResults:() -> @setState({currentPage: 0, next: null, show_all_artists: false, artists:[], jamtracks:[], type: 'user-input', searching:false, artist: null, song:null, is_free: @user.show_free_jamtrack, first_search: true}) getInitialState: () -> {search: '', type: 'user-input', artists:[], jamtracks:[], show_all_artists: false, currentPage: 0, next: null, searching: false, first_search: true, count: 0, is_free: context.JK.currentUserFreeJamTrack} onArtistClick: (artist, e) -> e.preventDefault() @search('artist-select', artist) onSelectChange: (val) -> return false unless val? search_type if val.indexOf('ARTIST=') == 0 search_type = 'artist-select' artist = val['ARTIST='.length..-1] @search(search_type, artist) else if val.indexOf('SONG=') == 0 search_type = 'song-select' song = val['SONG='.length..-1] @search(search_type, song) else @logger.debug("user selected separator") # this is to signal to the component that the separator was selected, and it has code in render to negate the selection setTimeout((() => @setState({search:val}) ), 1) return false onSelectBlur: (e) -> #@logger.debug("blur time") #@search() showAllArtists: () -> @setState({show_all_artists: true}) hideExtraArtists: () -> @setState({show_all_artists: false}) defaultQuery:(extra) -> query = per_page: @LIMIT page: @state.currentPage + 1 sort_by: 'jamtrack' if @state.next query.since = @state.next $.extend(query, extra) userSearch: (e) -> e.preventDefault() @search('user-input', window.JamTrackSearchInput) search: (search_type, input) -> return if @state.searching return unless input? window.JamTrackSearchInput = input $root = $(@getDOMNode()) # disable scroll watching now that we've started a new search #@logger.debug("disabling infinite scroll") $root.find('.content-body-scroller').off('scroll') $root.find('.end-of-jamtrack-list').hide() artistSearch = {limit:100} if search_type == 'artist-select' # the user wants to see just artists matching thes exact name artistSearch.artist = input else # the user wants to see anything sort of matching input artistSearch.artist_search = input if input? @rest.getJamTrackArtists(artistSearch) .done((response) => @setState({artists:response.artists}) # we have to make sure the query starts from page 1, and no 'next' from previous causes a 'since' to show up query = @defaultQuery({page: 1}) delete query.since @logger.debug("Search type", search_type) if search_type == 'artist-select' query.artist = input # works like exact match else if search_type == 'song-select' query.song = input # works as exact match else query.search = input # works with tsv @rest.getJamTracks(query) .done((response) => @setState({jamtracks: response.jamtracks, next: response.next, searching: false, first_search: false, currentPage: 1, count: response.count}) ) .fail((jqXHR) => @app.notifyServerError jqXHR, 'Search Unavailable' @setState({searching: false, first_search: false}) ) ) .fail((jqXHR) => @app.notifyServerError jqXHR, 'Search Unavailable' @setState({searching: false, first_search: false}) ) @setState({currentPage: 0, next: null, artists: [], jamtracks:[], searching: true, artist: input, song: input, type: search_type, search:input, count:0}) getOptions: (input, callback) => #@logger.debug("getOptions input #{input}", this) # sigh. ugly global window.JamTrackSearchInput = input if !input? || input.length == 0 callback(null, {options: [], complete: false}) return @rest.autocompleteJamTracks({match:input, limit:5}) .done((autocomplete) => options = [] for artist in autocomplete.artists options.push { value: "ARTIST=#{artist.original_artist}", label: "Artist: #{artist.original_artist}" } if options.length > 0 && autocomplete.songs.length > 0 options.push { value: 'SEPARATOR', label: "---------------"} for jamtrack in autocomplete.songs options.push { value: "SONG=#{jamtrack.name}", label: "Song: #{jamtrack.name}" } callback(null, {options: options, complete: false}) ) artistNavSelected: (e) -> e.preventDefault() @search('artist-select', $(e.target).attr('data-artist')) componentDidMount: () -> #@logger.debug("componentDidMount") componentDidUpdate: ( ) -> $root = $(this.getDOMNode()) $scroller = $root.find('.content-body-scroller') for jamTrack in @state.jamtracks jamtrackElement = $root.find("tbody .jamtrack-record[data-jamtrack-id=\"#{jamTrack.id}\"]") alreadyRegistered = jamtrackElement.data('registered') unless alreadyRegistered jamtrackElement.data('jamTrack', jamTrack) jamtrackElement.data('registered', true) jamtrackElement.data('expanded', true) @handleExpanded(jamtrackElement) @registerEvents(jamtrackElement) if @state.next == null $scroller = $root.find('.content-body-scroller') # if we less results than asked for, end searching #$scroller.infinitescroll 'pause' #@logger.debug("disabling infinite scroll") $scroller.off('scroll') if @state.currentPage == 1 and @state.jamtracks.length == 0 $root.find('.end-of-jamtrack-list').text('No JamTracks found matching your search').show() @logger.debug("JamTrackSearch: empty search") else if @state.currentPage > 0 @logger.debug("end of search") $noMoreJamtracks = $root.find('.end-of-jamtrack-list').text('No more JamTracks').show() # there are bugs with infinitescroll not removing the 'loading'. # it's most noticeable at the end of the list, so whack all such entries else @registerInfiniteScroll($scroller) registerInfiniteScroll:($scroller) -> @logger.debug("registering infinite scroll") $scroller.off('scroll') $scroller.on('scroll', () => # be sure to not fire off many refreshes when user hits the bottom return if @refreshing if $scroller.scrollTop() + $scroller.innerHeight() + 100 >= $scroller[0].scrollHeight $scroller.append('
... Loading more JamTracks ...
') @refreshing = true @setState({searching: true}) @logger.debug("refreshing more jamtracks for infinite scroll") @rest.getJamTracks(@defaultQuery({search:@state.search})) .done((json) => @setState({jamtracks: @state.jamtracks.concat(json.jamtracks), next: json.next, first_search: false, currentPage: @state.currentPage + 1, count: json.count}) ) .always(() => $scroller.find('.infinite-scroll-loader-2').remove() @refreshing = false @setState({searching: false}) ) ) playJamtrack:(e) -> e.preventDefault() addToCartJamtrack:(e) -> e.preventDefault() $target = $(e.target) params = id: $target.attr('data-jamtrack-id') params.variant = $target.attr('data-variant') isFree = $(e.target).is('.is_free') @rest.addJamtrackToShoppingCart(params).done((response) => console.log("added item to shopping cart. fast_redeem? " + response.fast_redeem) if response.fast_reedem if context.JK.currentUserId? context.location = '/client#/redeemComplete' else context.location = '/client#/redeemSignup' else context.location = '/client#/shoppingCart' ).fail(((jqxhr) => handled = false if jqxhr.status == 422 body = JSON.parse(jqxhr.responseText) if body.errors && body.errors.base handled = true context.JK.Banner.showAlert("You can not have a mix of free and non-free items in your shopping cart.

If you want to add this new item to your shopping cart, then clear out all current items by clicking on the shopping cart icon and clicking 'delete' next to each item.") if !handled @app.ajaxError(arguments[0], arguments[1], arguments[2]) )) licenseUSWhy:(e) -> e.preventDefault() @app.layout.showDialog 'jamtrack-availability-dialog' registerEvents:($parent) -> $parent.find('.play-button').on 'click', @playJamtrack $parent.find('.jamtrack-add-cart').on 'click', @addToCartJamtrack $parent.find('.license-us-why').on 'click', @licenseUSWhy $parent.find('.jamtrack-detail-btn').on 'click', @toggleExpanded $parent.find('.jamtrack-variant-help').on 'click', @showVariantHelp $parent.find('.jamtrack-upgrade-help').on 'click', @showUpgradeHelp showVariantHelp: (e) -> $screen = $('#jamtrackSearch') e.preventDefault() context.JK.HelpBubbleHelper.jamtrackVariants($(e.target), $screen) showUpgradeHelp: (e) -> $screen = $('#jamtrackSearch') e.preventDefault() context.JK.HelpBubbleHelper.jamtrackUpgrade($(e.target), $screen) toggleExpanded:(e) -> e.preventDefault() jamtrackRecord = $(e.target).parents('.jamtrack-record') @handleExpanded(jamtrackRecord) handleExpanded:(trackElement) -> jamTrack = trackElement.data('jamTrack') expanded = trackElement.data('expanded') expand = !expanded trackElement.data('expanded', expand) detailArrow = trackElement.find('.jamtrack-detail-btn') if expand trackElement.find('.extra').removeClass('hidden') detailArrow.html('hide tracks ') for track in jamTrack.tracks trackElement.find("[data-jamtrack-track-id='#{track.id}']").removeClass('hidden') else trackElement.find('.extra').addClass('hidden') detailArrow.html('show all tracks ') count = 0 for track in jamTrack.tracks if count < 6 trackElement.find("[data-jamtrack-track-id='#{track.id}']").removeClass('hidden') else trackElement.find("[data-jamtrack-track-id='#{track.id}']").addClass('hidden') count++ afterShow: (data) -> @setFilterFromURL() setFilterFromURL:() -> performSearch = false if $.QueryString['artist']? performSearch = true @search('artist-select', $.QueryString['artist']) else if $.QueryString['song']? performSearch = true @search('song-select', $.QueryString['song']) else if $.QueryString['search']? performSearch = true @search('user-input', $.QueryString['search']) else # check if someone has requested a search for us as we transition to this screen search = context.JamTrackStore.checkRequestedSearch() if search? performSearch = true @search(search.searchType, search.searchData) else if !@state.first_search @search(@state.type, window.JamTrackSearchInput) if performSearch if window.history.replaceState #ie9 proofing window.history.replaceState({}, "", "/client#/jamtrack/search") beforeShow: () -> onAppInit: (@app) -> window.JamTrackSearchInput = '' # need to be not null; otherwise react-select chokes @EVENTS = context.JK.EVENTS @rest = context.JK.Rest() @logger = context.JK.logger screenBindings = 'beforeShow': @beforeShow 'afterShow': @afterShow @app.bindScreen('jamtrack/search', screenBindings) onUserChanged: (userState) -> @user = userState?.user @setState({is_free: @user?.show_free_jamtrack}) })