* VRFS-3264 - help bubbles on jamtrack browse screen when not logged in, VRFS-3267 help IE11 visualize jamtrack browse page correctly

This commit is contained in:
Seth Call 2015-05-29 15:30:23 -05:00
parent 6e2145abea
commit 43b92d4a17
20 changed files with 391 additions and 16 deletions

View File

@ -418,12 +418,13 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
elsif quarter == 2
[Date.new(year, 7, 1), Date.new(year, 9, 30)]
elsif quarter == 3
[Date.new(year, 7, 1), Date.new(year, 9, 30)]
[Date.new(year, 10, 1), Date.new(year, 12, 31)]
else
raise "invalid quarter #{quarter}"
end
end
# 1-based month
def self.boundary_dates_for_month(year, month)
[Date.new(year, month, 1), Date.civil(year, month, -1)]
end

View File

@ -722,6 +722,116 @@ describe AffiliatePartner do
traffic_total_day2.signups.should eq(1)
end
end
describe "boundary_dates" do
it "1st quarter" do
start_date, end_date = AffiliatePartner.boundary_dates(2015, 0)
start_date.should eq(Date.new(2015, 1, 1))
end_date.should eq(Date.new(2015, 3, 31))
end
it "2nd quarter" do
start_date, end_date = AffiliatePartner.boundary_dates(2015, 1)
start_date.should eq(Date.new(2015, 4, 1))
end_date.should eq(Date.new(2015, 6, 30))
end
it "3rd quarter" do
start_date, end_date = AffiliatePartner.boundary_dates(2015, 2)
start_date.should eq(Date.new(2015, 7, 1))
end_date.should eq(Date.new(2015, 9, 30))
end
it "4th quarter" do
start_date, end_date = AffiliatePartner.boundary_dates(2015, 3)
start_date.should eq(Date.new(2015, 10, 1))
end_date.should eq(Date.new(2015, 12, 31))
end
end
describe "boundary_dates_for_month" do
it "invalid month" do
expect{AffiliatePartner.boundary_dates_for_month(2015, 0)}.to raise_error
end
it "January" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 1)
start_date.should eq(Date.new(2015, 1, 1))
end_date.should eq(Date.new(2015, 1, 31))
end
it "February" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 2)
start_date.should eq(Date.new(2015, 2, 1))
end_date.should eq(Date.new(2015, 2, 28))
end
it "March" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 3)
start_date.should eq(Date.new(2015, 3, 1))
end_date.should eq(Date.new(2015, 3, 31))
end
it "April" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 4)
start_date.should eq(Date.new(2015, 4, 1))
end_date.should eq(Date.new(2015, 4, 30))
end
it "May" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 5)
start_date.should eq(Date.new(2015, 5, 1))
end_date.should eq(Date.new(2015, 5, 31))
end
it "June" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 6)
start_date.should eq(Date.new(2015, 6, 1))
end_date.should eq(Date.new(2015, 6, 30))
end
it "July" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 7)
start_date.should eq(Date.new(2015, 7, 1))
end_date.should eq(Date.new(2015, 7, 31))
end
it "August" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 8)
start_date.should eq(Date.new(2015, 8, 1))
end_date.should eq(Date.new(2015, 8, 31))
end
it "September" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 9)
start_date.should eq(Date.new(2015, 9, 1))
end_date.should eq(Date.new(2015, 9, 30))
end
it "October" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 10)
start_date.should eq(Date.new(2015, 10, 1))
end_date.should eq(Date.new(2015, 10, 31))
end
it "November" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 11)
start_date.should eq(Date.new(2015, 11, 1))
end_date.should eq(Date.new(2015, 11, 30))
end
it "December" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 12)
start_date.should eq(Date.new(2015, 12, 1))
end_date.should eq(Date.new(2015, 12, 31))
end
it "February in a leap year" do
start_date, end_date = AffiliatePartner.boundary_dates_for_month(2016, 2)
start_date.should eq(Date.new(2016, 2, 1))
end_date.should eq(Date.new(2016, 2, 29))
end
end
end
end

View File

@ -36,6 +36,7 @@
//= require jquery.custom-protocol
//= require jquery.exists
//= require jquery.payment
//= require jquery.visible
//= require howler.core.js
//= require jstz
//= require class

View File

@ -52,7 +52,8 @@
JAMTRACK_DOWNLOADER_STATE_CHANGED: 'jamtrack_downloader_state',
METRONOME_PLAYBACK_MODE_SELECTED: 'metronome_playback_mode_selected',
CHECKOUT_SIGNED_IN: 'checkout_signed_in',
CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in'
CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in',
PREVIEW_PLAYED: 'preview_played'
};
context.JK.PLAYBACK_MONITOR_MODE = {

View File

@ -62,6 +62,24 @@
}
}
helpBubble.rotateJamTrackLandingBubbles = function($preview, $video, $ctaButton, $alternativeCta) {
$(window).on('load', function() {
setTimeout(function() {
helpBubble.jamtrackLandingPreview($preview, $preview.offsetParent())
setTimeout(function() {
helpBubble.jamtrackLandingVideo($video, $video.offsetParent())
setTimeout(function() {
helpBubble.jamtrackLandingCta($ctaButton, $alternativeCta)
}, 11000); // 5 seconds on top of 6 second show time of bubbles
}, 11000); // 5 seconds on top of 6 second show time of bubbles
}, 1500)
})
}
helpBubble.clearJamTrackGuide = clearJamTrackGuideTimeout;
helpBubble.jamtrackGuideTile = function ($element, $offsetParent) {
@ -82,4 +100,33 @@
})
}
helpBubble.jamtrackLandingPreview = function($element, $offsetParent) {
context.JK.prodBubble($element, 'jamtrack-landing-preview', {}, bigHelpOptions({positions:['right'], offsetParent: $offsetParent}))
}
helpBubble.jamtrackLandingVideo = function($element, $offsetParent) {
context.JK.prodBubble($element, 'jamtrack-landing-video', {}, bigHelpOptions({positions:['left'], offsetParent: $offsetParent}))
}
helpBubble.jamtrackLandingCta = function($element, $alternativeElement) {
if ($element.visible()) {
context.JK.prodBubble($element, 'jamtrack-landing-cta', {}, bigHelpOptions({positions:['left']}))
}
else {
context.JK.prodBubble($alternativeElement, 'jamtrack-landing-cta', {}, bigHelpOptions({positions:['right']}))
}
}
helpBubble.jamtrackBrowseBand = function($element, $offsetParent) {
return context.JK.prodBubble($element, 'jamtrack-browse-band', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent}))
}
helpBubble.jamtrackBrowseMasterMix = function($element, $offsetParent) {
return context.JK.prodBubble($element, 'jamtrack-browse-master-mix', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent}))
}
helpBubble.jamtrackBrowseCta = function($element, $offsetParent) {
return context.JK.prodBubble($element, 'jamtrack-browse-cta', {}, bigHelpOptions({positions:['top'], offsetParent: $offsetParent}))
}
})(window, jQuery);

View File

@ -129,6 +129,8 @@ context.JK.JamTrackPreview = class JamTrackPreview
if e?
e.stopPropagation()
$(this).triggerHandler(@EVENTS.PREVIEW_PLAYED)
if @no_audio
context.JK.prodBubble(@playButton, 'There is no preview available for this track.', {}, {duration:2000})
else

View File

@ -6,7 +6,8 @@ context.JK.JamTrackScreen=class JamTrackScreen
LIMIT = 10
instrument_logo_map = context.JK.getInstrumentIconMap24()
constructor: (@app) ->
constructor: (@app) ->
@EVENTS = context.JK.EVENTS
@logger = context.JK.logger
@screen = null
@content = null
@ -21,6 +22,7 @@ context.JK.JamTrackScreen=class JamTrackScreen
@next = null
@currentQuery = this.defaultQuery()
@expanded = null
@shownHelperBubbles = false
beforeShow:(data) =>
this.setFilterFromURL()
@ -38,11 +40,17 @@ context.JK.JamTrackScreen=class JamTrackScreen
)
else
this.refresh()
unless @shownHelperBubbles
@shownHelperBubbles = true
@startHelperBubbles()
afterShow:(data) =>
context.JK.Tracking.jamtrackBrowseTrack(@app)
beforeHide: () =>
this.clearCtaHelpTimeout()
this.clearBandFilterHelpTimeout()
this.clearMasterHelpTimeout()
this.clearResults();
events:() =>
@ -57,6 +65,104 @@ context.JK.JamTrackScreen=class JamTrackScreen
@noMoreJamtracks.hide()
@next = null
startHelperBubbles: () =>
@showBandFilterHelpTimeout = setTimeout(@showBandFilterHelp, 3500)
showBandFilterHelp: () =>
context.JK.HelpBubbleHelper.jamtrackBrowseBand(@artist.closest('.easydropdown-wrapper'), $('body'))
@showMasterHelpDueTime = new Date().getTime() + 11000 # 6000 ms for band tooltip to display, and 5 seconds of quiet time
@scroller.on('scroll', @masterHelpScrollWatch)
@scroller.on('scroll', @clearBubbles)
@showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime())
clearBubbles: () =>
if @helpBubble?
@helpBubble.btOff()
@helpBubble = null
# computes when we should show the master help bubble
masterHelpDueTime: () =>
dueTime = @showMasterHelpDueTime - new Date().getTime()
if dueTime <= 0
dueTime = 2000
dueTime
# computes when we should show the master help bubble
ctaHelpDueTime: () =>
dueTime = @showCtaHelpDueTime - new Date().getTime()
if dueTime <= 0
dueTime = 2000
dueTime
# if the user scrolls, reset the master help due time
masterHelpScrollWatch: () =>
@clearMasterHelpTimeout()
@showMasterHelpTimeout = setTimeout(@showMasterHelp, @masterHelpDueTime() + 2000)
# if the user scrolls, reset the master help due time
ctaHelpScrollWatch: () =>
@clearCtaHelpTimeout()
@showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime() + 2000)
showCtaHelp: () =>
@scroller.off('scroll', @ctaHelpScrollWatch)
@clearCtaHelpTimeout()
cutoff = @scroller.offset().top;
@screen.find('.jamtrack-actions').each((i, element) =>
$element = $(element)
if ($element.offset().top >= cutoff)
@helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseCta($element, $('body'))
return false
else
return true
)
showMasterHelp: () =>
@scroller.off('scroll', @masterHelpScrollWatch)
@clearMasterHelpTimeout()
# don't show the help if the user has already clicked a preview
unless @userPreviewed
cutoff = @scroller.offset().top;
@screen.find('.jamtrack-preview[data-track-type="Master"]').each((i, element) =>
$element = $(element)
if ($element.offset().top >= cutoff)
@helpBubble = context.JK.HelpBubbleHelper.jamtrackBrowseMasterMix($element.find('.play-button'), $('body'))
return false
else
return true
)
@showCtaHelpDueTime = new Date().getTime() + 11000
@scroller.on('scroll', @ctaHelpScrollWatch)
@showCtaHelpTimeout = setTimeout(@showCtaHelp, @ctaHelpDueTime()) # 6000 ms for bubble show time, and 5000ms for delay
previewPlayed: () =>
@userPreviewed = true
clearCtaHelpTimeout:() =>
if @showCtaHelpTimeout?
clearTimeout(@showCtaHelpTimeout)
@showCtaHelpTimeout = null
clearBandFilterHelpTimeout: () =>
if @showBandFilterHelpTimeout?
clearTimeout(@showBandFilterHelpTimeout)
@showBandFilterHelpTimeout = null
clearMasterHelpTimeout: () =>
if @showMasterHelpTimeout?
clearTimeout(@showMasterHelpTimeout)
@showMasterHelpTimeout = null
setFilterFromURL:() =>
# Grab parms from URL for artist, instrument, and availability
parms=this.getParams()
@ -73,7 +179,9 @@ context.JK.JamTrackScreen=class JamTrackScreen
@availability.val(parms.availability)
else
@availability.val('')
window.history.replaceState({}, "", "/client#/jamtrackBrowse")
if window.history.replaceState #ie9 proofing
window.history.replaceState({}, "", "/client#/jamtrackBrowse")
getParams:() =>
params = {}
@ -320,7 +428,8 @@ context.JK.JamTrackScreen=class JamTrackScreen
for track in jamTrack.tracks
trackRow = jamtrackElement.find("[jamtrack-track-id='#{track.id}']")
previewElement = trackRow.find(".jamtrack-preview")
new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'})
preview = new JK.JamTrackPreview(@app, previewElement, jamTrack, track, {master_shows_duration: true, color:'gray'})
$(preview).on(@EVENTS.PREVIEW_PLAYED, @previewPlayed)
this.handleExpanded(jamtrackElement, false)

View File

@ -72,7 +72,8 @@ context.JK.JamTrackLanding = class JamTrackLanding
that=this
@bandList.on "click", "a.artist-link", (event)->
context.location="client#/jamtrackBrowse"
window.history.replaceState({}, "", this.href)
if window.history.replaceState # ie9 proofing
window.history.replaceState({}, "", this.href)
event.preventDefault()
handleFailure:(error) =>

View File

@ -45,11 +45,13 @@
$previews.append($element);
new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break: true, preload_master:true})
if(track.track_type =='Master') {
context.JK.HelpBubbleHelper.rotateJamTrackLandingBubbles($element.find('.jam-track-preview'), $page.find('.video-wrapper'), $page.find('.cta-free-jamtrack a'), $page.find('a.browse-jamtracks'));
}
})
$previews.append('<br clear = "all" />')
})
.fail(function () {
app.notify({title: 'Unable to fetch JamTrack', text: "Please refresh the page or try again later."})

View File

@ -35,6 +35,10 @@
$previews.append($element);
new context.JK.JamTrackPreview(app, $element, jam_track, track, {master_shows_duration: false, color:'black', master_adds_line_break:true, preload_master:true})
if(track.track_type =='Master') {
context.JK.HelpBubbleHelper.rotateJamTrackLandingBubbles($element.find('.jam-track-preview'), $page.find('.video-wrapper'), $page.find('.cta-free-jamtrack a'), $page.find('a.browse-jamtracks'));
}
})
$previews.append('<br clear = "all" />')

View File

@ -20,6 +20,7 @@
//= require jquery.icheck
//= require jquery.bt
//= require jquery.exists
//= require jquery.visible
//= require howler.core.js
//= require AAA_Log
//= require AAC_underscore

View File

@ -50,6 +50,8 @@ body.jam, body.web, .dialog{
.big-help {
font-size:20px;
color: #ed3618;
p {color:#ed3618}
}
.help-hover-recorded-tracks, .help-hover-stream-mix, .help-hover-recorded-backing-tracks {

View File

@ -209,14 +209,10 @@
@include border_box_sizing;
width: 20%;
text-align: center;
vertical-align: middle;
.jamtrack-action-container {
display: flex;
align-items: center;
justify-content: center;
position:absolute;
height:100%;
width:100%;
display:inline-block;
}
.play-button {

View File

@ -261,4 +261,28 @@ script type="text/template" id="template-help-jamtrack-guide-private"
script type="text/template" id="template-help-jamtrack-guide-session"
.jamtrack-guide-open.big-help
p To try out your JamTrack, click here to open it.
p To try out your JamTrack, click here to open it.
script type="text/template" id="template-help-jamtrack-landing-preview"
.jamtrack-landing-preview.big-help
p click a play button to preview the master mix and individual tracks of the JamTrack
script type="text/template" id="template-help-jamtrack-landing-video"
.jamtrack-landing-video.big-help
p click to watch JamTracks video
script type="text/template" id="template-help-jamtrack-landing-cta"
.jamtrack-landing-cta.big-help
p click to browse through our JamTracks collection and get your first one free!
script type="text/template" id="template-help-jamtrack-browse-band"
.jamtrack-browse-band.big-help
p List JamTracks of a specified band
script type="text/template" id="template-help-jamtrack-browse-master-mix"
.jamtrack-browse-master-mix.big-help
p Listen to master mix and individual tracks
script type="text/template" id="template-help-jamtrack-browse-cta"
.jamtrack-browse-cta.big-help
p Click to select your first free JamTrack!

View File

@ -1,5 +1,6 @@
- provide(:page_name, 'landing_page full landing_jamtrack individual_jamtrack')
- provide(:description, @jam_track.nil? ? nil : "Preview multi-track JamTrack recording: #{@jam_track.name} by #{@jam_track.original_artist}. Way better than a backing track.")
- provide(:title, @jam_track.nil? ? nil : "Preview JamTrack: #{@jam_track.name} by #{@jam_track.original_artist}")
.one_by_two
.row

View File

@ -1,5 +1,6 @@
- provide(:page_name, 'landing_page full landing_jamtrack individual_jamtrack_band')
- provide(:description, @jam_track.nil? ? nil : "Preview multi-track JamTrack recording: #{@jam_track.name} by #{@jam_track.original_artist}. Way better than a backing track.")
- provide(:title, @jam_track.nil? ? nil : "Preview JamTrack: #{@jam_track.name} by #{@jam_track.original_artist}")
.one_by_two
.row

View File

@ -346,5 +346,7 @@ if defined?(Bundler)
config.expire_fingerprint_days = 14
config.found_conflict_count = 1
config.web_performance_timing_enabled = true
config.jamtrack_landing_bubbles_enabled = true
config.jamtrack_browser_bubbles_enabled = true
end
end

View File

@ -108,6 +108,6 @@ SampleApp::Application.configure do
config.jam_tracks_available = true
config.video_available = "full"
config.guard_against_fraud = true
config.error_on_fraud = true
config.error_on_fraud = false
end

View File

@ -17,4 +17,6 @@ Gon.global.gear_check_ignore_high_latency = Rails.application.config.gear_check_
Gon.global.purchases_enabled = Rails.application.config.purchases_enabled
Gon.global.estimate_taxes = Rails.application.config.estimate_taxes
Gon.global.web_performance_timing_enabled = Rails.application.config.web_performance_timing_enabled
Gon.global.jamtrack_landing_bubbles_enabled = Rails.application.config.jamtrack_landing_bubbles_enabled
Gon.global.jamtrack_browser_bubbles_enabled = Rails.application.config.jamtrack_browser_bubbles_enabled
Gon.global.env = Rails.env

View File

@ -0,0 +1,68 @@
(function($){
/**
* Copyright 2012, Digital Fusion
* Licensed under the MIT license.
* http://teamdf.com/jquery-plugins/license/
*
* @author Sam Sehnert
* @desc A small plugin that checks whether elements are within
* the user visible viewport of a web browser.
* only accounts for vertical position, not horizontal.
*/
var $w = $(window);
$.fn.visible = function(partial,hidden,direction){
if (this.length < 1)
return;
var $t = this.length > 1 ? this.eq(0) : this,
t = $t.get(0),
vpWidth = $w.width(),
vpHeight = $w.height(),
direction = (direction) ? direction : 'both',
clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true;
if (typeof t.getBoundingClientRect === 'function'){
// Use this native browser method, if available.
var rec = t.getBoundingClientRect(),
tViz = rec.top >= 0 && rec.top < vpHeight,
bViz = rec.bottom > 0 && rec.bottom <= vpHeight,
lViz = rec.left >= 0 && rec.left < vpWidth,
rViz = rec.right > 0 && rec.right <= vpWidth,
vVisible = partial ? tViz || bViz : tViz && bViz,
hVisible = partial ? lViz || rViz : lViz && rViz;
if(direction === 'both')
return clientSize && vVisible && hVisible;
else if(direction === 'vertical')
return clientSize && vVisible;
else if(direction === 'horizontal')
return clientSize && hVisible;
} else {
var viewTop = $w.scrollTop(),
viewBottom = viewTop + vpHeight,
viewLeft = $w.scrollLeft(),
viewRight = viewLeft + vpWidth,
offset = $t.offset(),
_top = offset.top,
_bottom = _top + $t.height(),
_left = offset.left,
_right = _left + $t.width(),
compareTop = partial === true ? _bottom : _top,
compareBottom = partial === true ? _top : _bottom,
compareLeft = partial === true ? _right : _left,
compareRight = partial === true ? _left : _right;
if(direction === 'both')
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
else if(direction === 'vertical')
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
else if(direction === 'horizontal')
return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
}
};
})(jQuery);