From 50815ebbd2575bfe9976d4d69d5c8be209a8dc6f Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 10 Nov 2012 08:26:10 -0500 Subject: [PATCH 1/5] add ability to delete band followings --- app/controllers/api_users_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api_users_controller.rb b/app/controllers/api_users_controller.rb index be2e23f2a..0b0aae165 100644 --- a/app/controllers/api_users_controller.rb +++ b/app/controllers/api_users_controller.rb @@ -82,7 +82,7 @@ class ApiUsersController < ApplicationController def following_destroy JamRuby::UserFollower.delete_all "(user_id = '#{params[:user_id]}' AND follower_id = '#{params[:id]}')" - #JamRuby::BandFollower.delete_all "(ban_id = '#{params[:band_id]}' AND follower_id = '#{params[:id]}')" + #JamRuby::BandFollower.delete_all "(band_id = '#{params[:band_id]}' AND follower_id = '#{params[:id]}')" respond_with responder: ApiResponder end From f5db91c695fc72af14a509030032a889b663e77b Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 10 Nov 2012 23:25:28 -0500 Subject: [PATCH 2/5] added first and last name fields --- app/controllers/api_music_sessions_controller.rb | 4 ++-- app/views/api_bands/follower_index.rabl | 8 ++++++-- app/views/api_bands/show.rabl | 2 +- app/views/api_search/index.rabl | 4 ++-- app/views/api_users/follower_index.rabl | 8 ++++++-- app/views/api_users/following_index.rabl | 8 ++++++-- app/views/api_users/friend_index.rabl | 2 +- app/views/api_users/index.rabl | 2 +- app/views/api_users/show.rabl | 4 ++-- config/routes.rb | 6 +----- 10 files changed, 28 insertions(+), 20 deletions(-) diff --git a/app/controllers/api_music_sessions_controller.rb b/app/controllers/api_music_sessions_controller.rb index 5c6b7497f..86427da98 100644 --- a/app/controllers/api_music_sessions_controller.rb +++ b/app/controllers/api_music_sessions_controller.rb @@ -114,7 +114,7 @@ class ApiMusicSessionsController < ApiController # send out notification to queue to the rest of the session # TODO: also this isn't necessarily a user leaving; it's a client leaving' - user_joined = @message_factory.user_joined_music_session(@music_session.id, current_user.id, current_user.name) + user_joined = @message_factory.user_joined_music_session(@music_session.id, current_user.id, current_user.first_name + " " + current_user.last_name) @mq_router.server_publish_to_session(@music_session, user_joined, sender = {:client_id => @connection.client_id}) respond_with @connection, responder: ApiResponder, :location => api_session_participant_detail_url(@connection.client_id) @@ -145,7 +145,7 @@ class ApiMusicSessionsController < ApiController # send out notification to queue to the rest of the session # TODO: we should rename the notification to music_session_participants_change or something # TODO: also this isn't necessarily a user leaving; it's a client leaving' - user_left = @message_factory.user_left_music_session(@music_session.id, current_user.id, current_user.name) + user_left = @message_factory.user_left_music_session(@music_session.id, current_user.id, current_user.first_name + " " + current_user.last_name) @mq_router.server_publish_to_session(@music_session, user_left, sender = {:client_id => @connection.client_id}) end diff --git a/app/views/api_bands/follower_index.rabl b/app/views/api_bands/follower_index.rabl index 3408346cd..c58c0c9ab 100644 --- a/app/views/api_bands/follower_index.rabl +++ b/app/views/api_bands/follower_index.rabl @@ -2,8 +2,12 @@ object @band.followers attributes :follower_id => :user_id -node :name do |follower| - follower.user.name +node :first_name do |follower| + follower.user.first_name +end + +node :last_name do |follower| + follower.user.last_name end node :city do |follower| diff --git a/app/views/api_bands/show.rabl b/app/views/api_bands/show.rabl index 0a942d3c3..1091dfd88 100644 --- a/app/views/api_bands/show.rabl +++ b/app/views/api_bands/show.rabl @@ -4,7 +4,7 @@ attributes :id, :name, :city, :state, :country, :website, :biography, :photo_url unless @band.users.nil? || @band.users.size == 0 child :users => :musicians do - attributes :id, :name, :photo_url + attributes :id, :first_name, :last_name, :photo_url # TODO: figure out how to omit empty arrays node :instruments do |user| diff --git a/app/views/api_search/index.rabl b/app/views/api_search/index.rabl index 05a954b28..92f48b4db 100644 --- a/app/views/api_search/index.rabl +++ b/app/views/api_search/index.rabl @@ -5,11 +5,11 @@ child(:bands => :bands) { } child(:musicians => :musicians) { - attributes :id, :name, :location, :photo_url + attributes :id, :first_name, :last_name :location, :photo_url } child(:fans => :fans) { - attributes :id, :name, :location, :photo_url + attributes :id, :first_name, :last_name, :location, :photo_url } child(:recordings => :recordings) { diff --git a/app/views/api_users/follower_index.rabl b/app/views/api_users/follower_index.rabl index 35122bee5..0d82e3b56 100644 --- a/app/views/api_users/follower_index.rabl +++ b/app/views/api_users/follower_index.rabl @@ -2,8 +2,12 @@ object @user.followers attributes :follower_id => :user_id -node :name do |follower| - follower.user.name +node :first_name do |follower| + follower.user.first_name +end + +node :last_name do |follower| + follower.user.last_name end node :city do |follower| diff --git a/app/views/api_users/following_index.rabl b/app/views/api_users/following_index.rabl index d1a31401b..12afb07f4 100644 --- a/app/views/api_users/following_index.rabl +++ b/app/views/api_users/following_index.rabl @@ -2,8 +2,12 @@ object @user.followings attributes :user_id -node :name do |following| - following.user.name +node :first_name do |following| + following.user.first_name +end + +node :last_name do |following| + following.user.last_name end node :city do |following| diff --git a/app/views/api_users/friend_index.rabl b/app/views/api_users/friend_index.rabl index 3e5c75cd2..9a2f27e74 100644 --- a/app/views/api_users/friend_index.rabl +++ b/app/views/api_users/friend_index.rabl @@ -1,3 +1,3 @@ object @user.friends -attributes :id, :name, :city, :state, :country, :email, :online \ No newline at end of file +attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online \ No newline at end of file diff --git a/app/views/api_users/index.rabl b/app/views/api_users/index.rabl index 34558346d..3064a1366 100644 --- a/app/views/api_users/index.rabl +++ b/app/views/api_users/index.rabl @@ -1,4 +1,4 @@ collection @users # do not retrieve all child collections when showing a list of users -attributes :id, :name, :city, :state, :country, :email, :online, :musician, :photo_url \ No newline at end of file +attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online, :musician, :photo_url \ No newline at end of file diff --git a/app/views/api_users/show.rabl b/app/views/api_users/show.rabl index a4589cac9..809637732 100644 --- a/app/views/api_users/show.rabl +++ b/app/views/api_users/show.rabl @@ -1,10 +1,10 @@ object @user -attributes :id, :name, :city, :state, :country, :email, :online, :photo_url, :friend_count, :follower_count, :following_count +attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online, :photo_url, :friend_count, :follower_count, :following_count unless @user.friends.nil? || @user.friends.size == 0 child :friends => :friends do - attributes :id, :name, :online + attributes :id, :first_name, :last_name, :online end end diff --git a/config/routes.rb b/config/routes.rb index c861a0482..1a38f3a13 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,11 +74,7 @@ SampleApp::Application.routes.draw do # band followers match '/bands/:id/followers' => 'api_bands#follower_index', :via => :get -=begin - # band followings - match '/bands/:id/followings' => 'api_bands#following_create', :via => :post - match '/bands/:id/followings/:user_id' => 'api_bands#following_destroy', :via => :delete -=end + # invitations match '/invitations/:id' => 'api_invitations#show', :via => :get, :as => 'api_invitation_detail' match '/invitations/:id' => 'api_invitations#delete', :via => :delete From fc1a5c46f1508b4b41c935353d39912ba510183a Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 10 Nov 2012 23:26:13 -0500 Subject: [PATCH 3/5] roll back --- app/controllers/api_music_sessions_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api_music_sessions_controller.rb b/app/controllers/api_music_sessions_controller.rb index 86427da98..c597a5634 100644 --- a/app/controllers/api_music_sessions_controller.rb +++ b/app/controllers/api_music_sessions_controller.rb @@ -114,7 +114,7 @@ class ApiMusicSessionsController < ApiController # send out notification to queue to the rest of the session # TODO: also this isn't necessarily a user leaving; it's a client leaving' - user_joined = @message_factory.user_joined_music_session(@music_session.id, current_user.id, current_user.first_name + " " + current_user.last_name) + user_joined = @message_factory.user_joined_music_session(@music_session.id, current_user.id, current_user.name) @mq_router.server_publish_to_session(@music_session, user_joined, sender = {:client_id => @connection.client_id}) respond_with @connection, responder: ApiResponder, :location => api_session_participant_detail_url(@connection.client_id) From 3fc3c57e201ef7403d21931987a02e682a00ee07 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 10 Nov 2012 23:35:56 -0500 Subject: [PATCH 4/5] added name back to avoid breaking --- app/views/api_bands/follower_index.rabl | 4 ++++ app/views/api_bands/show.rabl | 2 +- app/views/api_users/follower_index.rabl | 4 ++++ app/views/api_users/following_index.rabl | 4 ++++ app/views/api_users/friend_index.rabl | 2 +- app/views/api_users/index.rabl | 2 +- app/views/api_users/show.rabl | 4 ++-- 7 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/views/api_bands/follower_index.rabl b/app/views/api_bands/follower_index.rabl index c58c0c9ab..fb957fa93 100644 --- a/app/views/api_bands/follower_index.rabl +++ b/app/views/api_bands/follower_index.rabl @@ -10,6 +10,10 @@ node :last_name do |follower| follower.user.last_name end +node :name do |follower| + follower.user.name +end + node :city do |follower| follower.user.city end diff --git a/app/views/api_bands/show.rabl b/app/views/api_bands/show.rabl index 1091dfd88..6b7864cbf 100644 --- a/app/views/api_bands/show.rabl +++ b/app/views/api_bands/show.rabl @@ -4,7 +4,7 @@ attributes :id, :name, :city, :state, :country, :website, :biography, :photo_url unless @band.users.nil? || @band.users.size == 0 child :users => :musicians do - attributes :id, :first_name, :last_name, :photo_url + attributes :id, :first_name, :last_name, :name, :photo_url # TODO: figure out how to omit empty arrays node :instruments do |user| diff --git a/app/views/api_users/follower_index.rabl b/app/views/api_users/follower_index.rabl index 0d82e3b56..7b7b7b985 100644 --- a/app/views/api_users/follower_index.rabl +++ b/app/views/api_users/follower_index.rabl @@ -10,6 +10,10 @@ node :last_name do |follower| follower.user.last_name end +node :name do |follower| + follower.user.name +end + node :city do |follower| follower.user.city end diff --git a/app/views/api_users/following_index.rabl b/app/views/api_users/following_index.rabl index 12afb07f4..60a776fac 100644 --- a/app/views/api_users/following_index.rabl +++ b/app/views/api_users/following_index.rabl @@ -10,6 +10,10 @@ node :last_name do |following| following.user.last_name end +node :name do |follower| + follower.user.name +end + node :city do |following| following.user.city end diff --git a/app/views/api_users/friend_index.rabl b/app/views/api_users/friend_index.rabl index 9a2f27e74..47bbd619b 100644 --- a/app/views/api_users/friend_index.rabl +++ b/app/views/api_users/friend_index.rabl @@ -1,3 +1,3 @@ object @user.friends -attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online \ No newline at end of file +attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online \ No newline at end of file diff --git a/app/views/api_users/index.rabl b/app/views/api_users/index.rabl index 3064a1366..8f9bbf9a7 100644 --- a/app/views/api_users/index.rabl +++ b/app/views/api_users/index.rabl @@ -1,4 +1,4 @@ collection @users # do not retrieve all child collections when showing a list of users -attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online, :musician, :photo_url \ No newline at end of file +attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :musician, :photo_url \ No newline at end of file diff --git a/app/views/api_users/show.rabl b/app/views/api_users/show.rabl index 809637732..c8f8ae3e5 100644 --- a/app/views/api_users/show.rabl +++ b/app/views/api_users/show.rabl @@ -1,10 +1,10 @@ object @user -attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online, :photo_url, :friend_count, :follower_count, :following_count +attributes :id, :first_name, :last_name, :name, :city, :state, :country, :email, :online, :photo_url, :friend_count, :follower_count, :following_count unless @user.friends.nil? || @user.friends.size == 0 child :friends => :friends do - attributes :id, :first_name, :last_name, :online + attributes :id, :first_name, :last_name, :name, :online end end From 1239cad08fd3d6ed5cd6c89e225538e985cb860b Mon Sep 17 00:00:00 2001 From: Jonathon Wilson Date: Sun, 11 Nov 2012 13:34:05 -0700 Subject: [PATCH 5/5] Good chunk of user profile (VRFS-74) --- app/assets/javascripts/header.js | 184 ++++++++++++++++++ app/assets/javascripts/homeScreen.js | 20 ++ app/assets/javascripts/jamkazam.js | 17 +- app/assets/javascripts/jquery.hoverIntent.js | 106 ++++++++++ .../stylesheets/client/jamkazam.css.scss | 45 ++++- app/views/clients/index.html.erb | 114 ++++++++++- 6 files changed, 464 insertions(+), 22 deletions(-) create mode 100644 app/assets/javascripts/header.js create mode 100644 app/assets/javascripts/homeScreen.js create mode 100644 app/assets/javascripts/jquery.hoverIntent.js diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js new file mode 100644 index 000000000..6c0733b90 --- /dev/null +++ b/app/assets/javascripts/header.js @@ -0,0 +1,184 @@ +(function(context,$) { + + /** + * Javascript for managing the header (account dropdown) as well + * as any dialogs reachable from there. Account settings dialog. + */ + + context.JK = context.JK || {}; + context.JK.Header = function(app) { + + var logger = context.JK.logger; + var userMe = null; + var instrumentAutoComplete; + var instrumentIds = []; + var instrumentNames = []; + var instrumentPopularities = {}; // id -> popularity + + function loadInstruments() { + // TODO: This won't work in the long-term. We'll need to provide + // a handlers which accepts some characters and only returns users + // who are musicians who match that input string. Once we get there, + // we could just use the ajax functionality of the autocomplete plugin. + // + // But for now: + // Load the users list into our local array for autocomplete. + $.ajax({ + type: "GET", + url: "/api/instruments" + }).done(function(response) { + $.each(response, function() { + instrumentNames.push(this.description); + instrumentIds.push(this.id); + // TODO - unused at the moment. + instrumentPopularities[this.id] = this.popularity; + }); + // Hook up the autocomplete. + var options = { + lookup: {suggestions:instrumentNames, data: instrumentIds}, + onSelect: addInstrument, + width: 120 + }; + if (!(instrumentAutoComplete)) { // Shouldn't happen here. Header only drawn once. + instrumentAutoComplete = $('#profile-instruments').autocomplete(options); + } else { + instrumentAutoComplete.setOptions(options); + } + }); + } + + function addInstrument(value, data) { + var instrumentName = value; + var instrumentId = data; + var template = $('#template-profile-instrument').html(); // TODO: cache this + var instrumentHtml = JK.fillTemplate( + template, {instrumentId: instrumentId, instrumentName: instrumentName}); + $('#added-profile-instruments').append(instrumentHtml); + $('#profile-instruments').select(); + } + + function setProficiency(id, proficiency) { + logger.debug("setProficiency: " + id + ',' + proficiency); + var selector = '#added-profile-instruments div.profile-instrument[instrument-id="' + + id + '"] select'; + logger.debug("Finding select to set proficiency. Length? " + $(selector).length); + $(selector).val(proficiency); + } + + function removeInvitation(evt) { + $(this).closest('.profile-instrument').remove(); + } + + function events() { + $('.username').on('click', function() { + $('ul', this).toggle(); + }); + + $('#account-identity-form').submit(handleIdentitySubmit); + $('#account-profile-form').submit(handleProfileSubmit); + // Remove added instruments when 'X' is clicked + $('#added-profile-instruments').on("click", ".instrument span", removeInvitation); + } + + function handleIdentitySubmit(evt) { + evt.preventDefault(); + user = $(this).formToObject(); + if (!user.password) { + delete user.password; + delete user.password_confirmation; + } + logger.debug("submitting identity form with:"); + logger.debug(user); + $.ajax({ + type: "POST", + url: "/api/users/" + userMe.id, + contentType: "application/json", + processData:false, + data: JSON.stringify(user) + }).done(function(response) { + userMe = response; + }).fail(function(jqXHR, textStatus, errorMessage) { + app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText}); + }); + return false; + } + + function handleProfileSubmit(evt) { + evt.preventDefault(); + var user = { + name: $('#account-profile-form input[name="name"]').val(), + instruments: [] + }; + $added_instruments = $('.profile-instrument', '#added-profile-instruments'); + var count = 1; + $.each($added_instruments, function() { + var instrumentId = $(this).attr('instrument-id'); + var proficiency = $('select', this).val(); + logger.debug("Instrument ID:" + instrumentId + ", proficiency: " + proficiency); + var instrument = { + id: instrumentId, + proficiency_level: proficiency, + priority: count++ + }; + user.instruments.push(instrument); + }); + + logger.debug("About to submit profile. User:"); + logger.debug(user); + + $.ajax({ + type: "POST", + url: "/api/users/" + userMe.id, + contentType: "application/json", + processData:false, + data: JSON.stringify(user) + }).done(function(response) { + userMe = response; + }).fail(function(jqXHR, textStatus, errorMessage) { + app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText}); + }); + + return false; + } + + function loadMe() { + logger.debug("loadMe"); + logger.debug("current user: " + JK.currentUserId); + $.ajax({ + url: '/api/users/' + JK.currentUserId + }).done(function(r) { + userMe = r; + updateAccountForms(); + }).fail(function(jqXHR, textStatus, errorMessage) { + app.notify({title: textStatus, text: errorMessage, detail: jqXHR.responseText}); + }); + } + + function updateAccountForms() { + var idTemplate = $('#template-identity-summary').html(); + var idHtml = JK.fillTemplate(idTemplate, userMe); + $('#identity-summary').html(idHtml); + // TODO: + // Make a thing that puts a JSON object into a form + // and fill the profile part of the form from the JSON. + // Short-term thing for now: + $('#account-identity-form input[name="email"]').val(userMe.email); + + // Profile form + $('#account-profile-form input[name="name"]').val(userMe.name); + if ("instruments" in userMe) { + $.each(userMe.instruments, function() { + addInstrument(this.description, this.id); + setProficiency(this.id, this.proficiency_level); + }); + } + } + + this.initialize = function() { + events(); + loadInstruments(); + loadMe(); + }; + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/homeScreen.js b/app/assets/javascripts/homeScreen.js new file mode 100644 index 000000000..22fca427e --- /dev/null +++ b/app/assets/javascripts/homeScreen.js @@ -0,0 +1,20 @@ +(function(context,$) { + + context.JK = context.JK || {}; + context.JK.HomeScreen = function(app) { + + function events() { + $('.homecard').on('mouseenter', function() { + $(this).addClass('hover'); + }); + $('.homecard').on('mouseleave', function() { + $(this).removeClass('hover'); + }); + } + + this.initialize = function() { + events(); + }; + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/javascripts/jamkazam.js b/app/assets/javascripts/jamkazam.js index e0e7aa666..d01b895bd 100644 --- a/app/assets/javascripts/jamkazam.js +++ b/app/assets/javascripts/jamkazam.js @@ -37,18 +37,6 @@ $(routes.handler); } - /** - * Some simple events for hovering on the home page. May want to move to a separate file. - */ - function events() { - $('.homecard').on('mouseenter', function() { - $(this).addClass('hover'); - }); - $('.homecard').on('mouseleave', function() { - $(this).removeClass('hover'); - }); - } - /** * Handle a websocket message */ @@ -72,13 +60,13 @@ } function _heartbeat() { - //logger.debug("...sending heartbeat"); message = context.JK.MessageFactory.heartbeat(); context.JK.JamServer.send(message); } function loggedIn(header, payload) { logger.debug('loggedIn'); + logger.debug(payload); app.clientId = payload.client_id; } @@ -97,7 +85,7 @@ logger.debug("registering " + message); context.JK.JamServer.registerMessageCallback(message, handleMessage); } - // Specifically register a handler for LOGIN_ACK to setup the heartbeat calls. + // Setup the heartbeat calls: context.JK.JamServer.registerMessageCallback(context.JK.MessageType.LOGIN_ACK, _handleLoginAck); } @@ -151,7 +139,6 @@ routing(); registerMessages(); registerLoginAck(); - events(); hash = location.hash; url = '#/home'; diff --git a/app/assets/javascripts/jquery.hoverIntent.js b/app/assets/javascripts/jquery.hoverIntent.js new file mode 100644 index 000000000..3dcff261f --- /dev/null +++ b/app/assets/javascripts/jquery.hoverIntent.js @@ -0,0 +1,106 @@ +/** +* hoverIntent is similar to jQuery's built-in "hover" function except that +* instead of firing the onMouseOver event immediately, hoverIntent checks +* to see if the user's mouse has slowed down (beneath the sensitivity +* threshold) before firing the onMouseOver event. +* +* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+ +* +* +* hoverIntent is currently available for use in all personal or commercial +* projects under both MIT and GPL licenses. This means that you can choose +* the license that best suits your project, and use it accordingly. +* +* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions +* $("ul li").hoverIntent( showNav , hideNav ); +* +* // advanced usage receives configuration object only +* $("ul li").hoverIntent({ +* sensitivity: 7, // number = sensitivity threshold (must be 1 or higher) +* interval: 100, // number = milliseconds of polling interval +* over: showNav, // function = onMouseOver callback (required) +* timeout: 0, // number = milliseconds delay before onMouseOut function call +* out: hideNav // function = onMouseOut callback (required) +* }); +* +* @param f onMouseOver function || An object with configuration options +* @param g onMouseOut function || Nothing (use configuration options object) +* @author Brian Cherne brian(at)cherne(dot)net +*/ +(function($) { + $.fn.hoverIntent = function(f,g) { + // default configuration options + var cfg = { + sensitivity: 7, + interval: 100, + timeout: 0 + }; + // override configuration options with user supplied object + cfg = $.extend(cfg, g ? { over: f, out: g } : f ); + + // instantiate variables + // cX, cY = current X and Y position of mouse, updated by mousemove event + // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval + var cX, cY, pX, pY; + + // A private function for getting mouse position + var track = function(ev) { + cX = ev.pageX; + cY = ev.pageY; + }; + + // A private function for comparing current and previous mouse position + var compare = function(ev,ob) { + ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); + // compare mouse positions to see if they've crossed the threshold + if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) { + $(ob).unbind("mousemove",track); + // set hoverIntent state to true (so mouseOut can be called) + ob.hoverIntent_s = 1; + return cfg.over.apply(ob,[ev]); + } else { + // set previous coordinates for next time + pX = cX; pY = cY; + // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs) + ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval ); + } + }; + + // A private function for delaying the mouseOut function + var delay = function(ev,ob) { + ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); + ob.hoverIntent_s = 0; + return cfg.out.apply(ob,[ev]); + }; + + // A private function for handling mouse 'hovering' + var handleHover = function(e) { + // copy objects to be passed into t (required for event object to be passed in IE) + var ev = jQuery.extend({},e); + var ob = this; + + // cancel hoverIntent timer if it exists + if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); } + + // if e.type == "mouseenter" + if (e.type == "mouseenter") { + // set "previous" X and Y position based on initial entry point + pX = ev.pageX; pY = ev.pageY; + // update "current" X and Y position based on mousemove + $(ob).bind("mousemove",track); + // start polling interval (self-calling timeout) to compare mouse coordinates over time + if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );} + + // else e.type == "mouseleave" + } else { + // unbind expensive mousemove event + $(ob).unbind("mousemove",track); + // if hoverIntent state is true, then call the mouseOut function after the specified delay + if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );} + } + }; + + // bind the function to the two event listeners + return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover); + }; +})(jQuery); \ No newline at end of file diff --git a/app/assets/stylesheets/client/jamkazam.css.scss b/app/assets/stylesheets/client/jamkazam.css.scss index d8c9883fa..c105e9bbe 100644 --- a/app/assets/stylesheets/client/jamkazam.css.scss +++ b/app/assets/stylesheets/client/jamkazam.css.scss @@ -64,6 +64,15 @@ label { display:block; } +.button1 { + background: $color1; + color: #fff !important; + font-weight:bold; + font-size: 120%; + margin: 2px; + padding:8px; +} + .hidden { display:none; } @@ -82,6 +91,31 @@ label { font-weight:bold; } +.dialog { + background-color:$color8; + border: #666; + color:#000; + min-width: 400px; + min-height: 350px; +} + +.dialog a { + color: $color1; +} + +.dialog h1 { + font-weight: bold; + font-size: 150%; + margin: 12px; +} +.dialog .panel { + background-color: shade($color8, 6%); + margin:12px; + padding: 12px; +} + + + .header h1 { margin:22px; font-size:300%; @@ -126,7 +160,7 @@ label { .screen.secondary { } -.screen.secondary .footer { +.buttonrow, .screen.secondary .footer { position: absolute; bottom:0px; right:0px; @@ -279,7 +313,8 @@ label { clear:both; } -.invitation { +/* TODO - generalize */ +.instrument, .invitation { margin: 1px; background: $color8; color:#000; @@ -288,12 +323,16 @@ label { float:left; } -.invitation span { +.instrument span, .invitation span { font-size:85%; font-weight:bold; cursor:pointer; } +.profiency { + float:left; +} + /* Autocomplete */ .autocomplete { border:1px solid #999; diff --git a/app/views/clients/index.html.erb b/app/views/clients/index.html.erb index 82a8459a2..59c0ebbed 100644 --- a/app/views/clients/index.html.erb +++ b/app/views/clients/index.html.erb @@ -7,7 +7,7 @@

<%= current_user.name %>

<%= image_tag "down_arrow.png", :class=> "profile-toggle" %>
    -
  • Profile
  • +
  • Profile
  • <%= link_to "Sign out", signout_path, method: "delete" %>
@@ -39,6 +39,7 @@ +