From dc462d804d8f54e7e15da9841d3b9e3d5d5ddab2 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 10 Feb 2014 22:43:09 +0000 Subject: [PATCH] * VRFS-982 - style with custom easydropdown instead of select element --- .../assets/javascripts/accounts_profile.js | 15 +- web/app/assets/javascripts/application.js | 6 + web/app/assets/javascripts/band_setup.js | 19 +- ...{createSession.js => createSession.js.erb} | 7 +- web/app/assets/javascripts/custom_controls.js | 5 + web/app/assets/javascripts/facebook_helper.js | 2 +- web/app/assets/javascripts/ftue.js | 35 +- web/app/assets/javascripts/genreSelector.js | 2 +- .../assets/javascripts/instrumentSelector.js | 5 +- .../assets/javascripts/invitationDialog.js | 1 + .../assets/javascripts/jquery.monkeypatch.js | 20 +- web/app/assets/javascripts/landing/signup.js | 32 +- web/app/assets/javascripts/utils.js | 14 + web/app/assets/javascripts/web/web.js | 5 + .../stylesheets/client/account.css.scss | 46 +- .../assets/stylesheets/client/band.css.scss | 11 + web/app/assets/stylesheets/client/client.css | 2 + .../stylesheets/client/createSession.css.scss | 4 +- .../assets/stylesheets/client/ftue.css.scss | 11 +- .../stylesheets/client/musician.css.scss | 5 + .../stylesheets/easydropdown_jk.css.scss | 181 +++++++ web/app/assets/stylesheets/web/main.css.scss | 11 + web/app/assets/stylesheets/web/web.css | 2 + .../views/clients/_account_profile.html.erb | 2 +- web/app/views/clients/_createSession.html.erb | 10 +- web/app/views/clients/_ftue.html.erb | 20 +- web/app/views/clients/_genreSelector.html.erb | 2 +- .../views/clients/_musician_filter.html.erb | 2 +- web/app/views/clients/_web_filter.html.erb | 14 +- web/app/views/layouts/client.html.erb | 2 +- web/app/views/layouts/corporate.html.erb | 2 +- web/app/views/layouts/landing.erb | 2 +- web/app/views/layouts/web.erb | 2 +- web/app/views/users/new.html.erb | 8 +- web/config/application.rb | 2 + web/config/environments/development.rb | 3 + web/config/initializers/gon.rb | 3 +- web/spec/features/musician_search_spec.rb | 7 +- web/spec/support/utilities.rb | 24 +- .../assets/javascripts/jquery.easydropdown.js | 504 ++++++++++++++++++ .../assets/stylesheets/easydropdown.css | 204 +++++++ 41 files changed, 1138 insertions(+), 116 deletions(-) rename web/app/assets/javascripts/{createSession.js => createSession.js.erb} (97%) create mode 100644 web/app/assets/javascripts/custom_controls.js create mode 100644 web/app/assets/stylesheets/easydropdown_jk.css.scss create mode 100644 web/vendor/assets/javascripts/jquery.easydropdown.js create mode 100644 web/vendor/assets/stylesheets/easydropdown.css diff --git a/web/app/assets/javascripts/accounts_profile.js b/web/app/assets/javascripts/accounts_profile.js index 615bdf708..d5880f1f1 100644 --- a/web/app/assets/javascripts/accounts_profile.js +++ b/web/app/assets/javascripts/accounts_profile.js @@ -44,6 +44,7 @@ }); var content_root = $('#account-profile-content-scroller') + content_root.html(template); // now use javascript to fix up values too hard to do with templating @@ -71,7 +72,11 @@ description : instrument.description, id : instrument.id }) + + $('.instrument_selector', content_root).append(template) + + }) // and fill in the proficiency for the instruments that the user can play if(userDetail.instruments) { @@ -79,6 +84,8 @@ $('tr[data-instrument-id="' + userInstrument.instrument_id + '"] select.proficiency_selector', content_root).val(userInstrument.proficiency_level) }) } + + context.JK.dropdown($('select', content_root)); } function isUserInstrument(instrument, userInstruments) { @@ -136,6 +143,8 @@ countrySelect.val(userCountry); countrySelect.attr("disabled", null) + + context.JK.dropdown(countrySelect); } @@ -159,6 +168,8 @@ regionSelect.val(userRegion) regionSelect.attr("disabled", null) + + context.JK.dropdown(regionSelect); } function populateCities(cities, userCity) { @@ -181,6 +192,8 @@ citySelect.val(userCity) citySelect.attr("disabled", null) + + context.JK.dropdown(citySelect); } /****************** MAIN PORTION OF SCREEN *****************/ @@ -258,8 +271,6 @@ .always(function() { loadingCitiesData = false;}) } } - - }) } diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index ff4d61a56..e180fa24f 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -11,6 +11,7 @@ // GO AFTER THE REQUIRES BELOW. // //= require jquery +//= require jquery.monkeypatch //= require jquery_ujs //= require jquery.ui.draggable //= require jquery.bt @@ -22,5 +23,10 @@ //= require jquery.queryparams //= require jquery.clipboard //= require jquery.timeago +//= require jquery.easydropdown //= require globals +//= require AAB_message_factory +//= require AAC_underscore +//= require utils +//= require custom_controls //= require_directory . diff --git a/web/app/assets/javascripts/band_setup.js b/web/app/assets/javascripts/band_setup.js index 0e861c06a..f2ec4bb99 100644 --- a/web/app/assets/javascripts/band_setup.js +++ b/web/app/assets/javascripts/band_setup.js @@ -5,7 +5,7 @@ context.JK = context.JK || {}; // TODO: MUCH OF THIS CLASS IS REPEATED IN THE FOLLOWING FILES: - // createSession.js + // createSession.js.erb // accounts_profiles.js context.JK.BandSetupScreen = function(app) { @@ -293,7 +293,7 @@ }); } - // TODO: this is repeated in createSession.js + // TODO: this is repeated in createSession.js.erb function loadFriends() { rest.getFriends({ id: context.JK.currentUserId }) .done(function(friends) { @@ -374,6 +374,8 @@ $country.append(option); }); + context.JK.dropdown($country); + if (onCountriesLoaded) { onCountriesLoaded(); } @@ -381,9 +383,9 @@ } function loadRegions(initialRegion, onRegionsLoaded) { - $("#band-region").empty(); - var selectedCountry = $("#band-country").val(); var $region = $("#band-region"); + $region.empty(); + var selectedCountry = $("#band-country").val(); var nilOption = $(''); nilOption.text(nilOptionText); @@ -404,6 +406,9 @@ $region.append(option); }); + + context.JK.dropdown($region); + if (onRegionsLoaded) { onRegionsLoaded(); } @@ -412,10 +417,10 @@ } function loadCities(initialCity) { - $("#band-city").empty(); + var $city = $("#band-city"); + $city.empty(); var selectedCountry = $("#band-country").val(); var selectedRegion = $("#band-region").val(); - var $city = $("#band-city"); var nilOption = $(''); nilOption.text(nilOptionText); @@ -435,6 +440,8 @@ $city.append(option); }); + + context.JK.dropdown($city); }); } } diff --git a/web/app/assets/javascripts/createSession.js b/web/app/assets/javascripts/createSession.js.erb similarity index 97% rename from web/app/assets/javascripts/createSession.js rename to web/app/assets/javascripts/createSession.js.erb index 84dc981df..5d7006abe 100644 --- a/web/app/assets/javascripts/createSession.js +++ b/web/app/assets/javascripts/createSession.js.erb @@ -23,7 +23,11 @@ } function resetForm() { + <% if Rails.application.config.autocheck_create_session_agreement %> + $('#intellectual-property').iCheck('check').attr('checked', true); + <% else %> $('#intellectual-property').iCheck('uncheck').attr('checked', false); + <% end %> var $form = $('#create-session-form'); var description = sessionSettings.hasOwnProperty('description') ? sessionSettings.description : ''; @@ -149,8 +153,6 @@ var jsonData = JSON.stringify(data); - console.log("session data=" + jsonData); - $('#btn-create-session').addClass('button-disabled'); $('#btn-create-session').bind('click', false); @@ -246,6 +248,7 @@ var bandOptionHtml = context.JK.fillTemplate(template, {value: this.id, label: this.name}); $('#band-list').append(bandOptionHtml); }); + context.JK.dropdown($('#band-list')); } function loadSessionSettings() { diff --git a/web/app/assets/javascripts/custom_controls.js b/web/app/assets/javascripts/custom_controls.js new file mode 100644 index 000000000..c6829c9b4 --- /dev/null +++ b/web/app/assets/javascripts/custom_controls.js @@ -0,0 +1,5 @@ +(function(context, $) { + $(function() { + context.JK.dropdown($('select.easydropdown')) + }) +})(window, jQuery); diff --git a/web/app/assets/javascripts/facebook_helper.js b/web/app/assets/javascripts/facebook_helper.js index b1ac43e07..8c00475ba 100644 --- a/web/app/assets/javascripts/facebook_helper.js +++ b/web/app/assets/javascripts/facebook_helper.js @@ -55,7 +55,7 @@ // channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', status : true, // check the login status upon init? cookie : true, // set sessions cookies to allow server to access the session? - xfbml : true, // parse XFBML tags on this page? + xfbml : false, // parse XFBML tags on this page? oauth : true // enable OAuth 2.0 }); diff --git a/web/app/assets/javascripts/ftue.js b/web/app/assets/javascripts/ftue.js index 8b145ccdd..610b81d77 100644 --- a/web/app/assets/javascripts/ftue.js +++ b/web/app/assets/javascripts/ftue.js @@ -367,8 +367,9 @@ var sortedDeviceKeys = context._.keys(devices).sort(); context._.each(sortedDeviceKeys, deviceOptionFunc); $select.html(optionsHtml); + context.JK.dropdown($select); $select.removeAttr("disabled"); - $('[layout-wizard-step="2"] .settings-asio select').removeAttr("disabled"); + $('[layout-wizard-step="2"] .settings-asio select').removeAttr("disabled").easyDropDown('enable') // Set selects to lowest possible values to start: $('#asio-framesize').val('2.5').change(); $('#asio-input-latency').val('0').change(); @@ -406,6 +407,7 @@ var $select = $(selector); $select.empty(); $select.html(optionsHtml); + context.JK.dropdown($select); }); } @@ -516,7 +518,6 @@ var latency = jamClient.FTUEGetExpectedLatency(); newFtueUpdateLatencyView(latency); - } function newFtueSave(persist) { @@ -568,13 +569,13 @@ var $bin = $('#ftue-2-asio-input-latency'); var $bout = $('#ftue-2-asio-output-latency'); if (enable) { - $frame.removeAttr("disabled"); - $bin.removeAttr("disabled"); - $bout.removeAttr("disabled"); + $frame.removeAttr("disabled").easyDropDown('enable'); + $bin.removeAttr("disabled").easyDropDown('enable'); + $bout.removeAttr("disabled").easyDropDown('enable'); } else { - $frame.attr("disabled", "disabled"); - $bin.attr("disabled", "disabled"); - $bout.attr("disabled", "disabled"); + $frame.attr("disabled", "disabled").easyDropDown('disable'); + $bin.attr("disabled", "disabled").easyDropDown('disable'); + $bout.attr("disabled", "disabled".easyDropDown('disable')); } } @@ -590,25 +591,25 @@ // Win32 + ControlPanel = ASIO // frame=2.5, buffers=0 $asioBtn.show(); - $frame.val(2.5); - $bin.val(0); - $bout.val(0); + $frame.val('2.5'); + $bin.val('0'); + $bout.val('0'); } else { // Win32, no ControlPanel = WDM/Kernel Streaming // frame=10, buffers=0 $asioBtn.hide(); - $frame.val(10); + $frame.val('10'); // TODO FIXME - the old FTUE set the buffers to 1 for WDM/Kernel streaming // The new FTUE spec says to use 0, as I've done here... - $bin.val(0); - $bout.val(0); + $bin.val('0'); + $bout.val('0'); } } else { // Assuming Mac. TODO: Linux check here // frame=2.5, buffers=0 $asioBtn.hide(); - $frame.val(2.5); - $bin.val(0); - $bout.val(0); + $frame.val('2.5'); + $bin.val('0'); + $bout.val('0'); } } diff --git a/web/app/assets/javascripts/genreSelector.js b/web/app/assets/javascripts/genreSelector.js index 7022cee5a..0aaed1ff0 100644 --- a/web/app/assets/javascripts/genreSelector.js +++ b/web/app/assets/javascripts/genreSelector.js @@ -46,6 +46,7 @@ var genreOptionHtml = context.JK.fillTemplate(template, value); $('select', parentSelector).append(genreOptionHtml); }); + } function getSelectedGenres(parentSelector) { @@ -65,7 +66,6 @@ $.each(genreList, function(index, value) { values.push(value.toLowerCase()); }); - console.log("OH HAI O") var selectedVal = $('select', parentSelector).val(values); } diff --git a/web/app/assets/javascripts/instrumentSelector.js b/web/app/assets/javascripts/instrumentSelector.js index 0c75e8575..10dbd0837 100644 --- a/web/app/assets/javascripts/instrumentSelector.js +++ b/web/app/assets/javascripts/instrumentSelector.js @@ -25,6 +25,7 @@ function reset(parentSelector, defaultGenre) { defaultGenre = typeof(defaultGenre) == 'undefined' ? '' : defaultGenre; $('select', parentSelector).val(defaultGenre); + //$('select', parentSelector).easyDropDown('select',defaultGenre) } function genresLoaded(response) { @@ -38,7 +39,7 @@ function render(parentSelector) { $('select', parentSelector).empty(); - $('select', parentSelector).append(''); + $('select', parentSelector).append(''); var template = $('#template-genre-option').html(); $.each(_genres, function(index, value) { // value will be a dictionary entry from _genres: @@ -46,6 +47,7 @@ var genreOptionHtml = context.JK.fillTemplate(template, value); $('select', parentSelector).append(genreOptionHtml); }); + context.JK.dropdown($('select', parentSelector)); } function getSelectedGenres(parentSelector) { @@ -65,6 +67,7 @@ $.each(genreList, function(index, value) { values.push(value.toLowerCase()); }); + var selectedVal = $('select', parentSelector).val(values); } diff --git a/web/app/assets/javascripts/invitationDialog.js b/web/app/assets/javascripts/invitationDialog.js index f337b690d..4fe5bbf19 100644 --- a/web/app/assets/javascripts/invitationDialog.js +++ b/web/app/assets/javascripts/invitationDialog.js @@ -185,6 +185,7 @@ description: '', actions: [{ name: 'Signup', link: signupUrl }] }; + console.log("facebook feed options:", obj); function fbFeedDialogCallback(response) { //console.log("feedback dialog closed: " + response['post_id']) if (response['post_id']) { diff --git a/web/app/assets/javascripts/jquery.monkeypatch.js b/web/app/assets/javascripts/jquery.monkeypatch.js index bb8b6946b..0e72bf533 100644 --- a/web/app/assets/javascripts/jquery.monkeypatch.js +++ b/web/app/assets/javascripts/jquery.monkeypatch.js @@ -1,26 +1,9 @@ - -/** -(function ($) { - $.valHooks['easydropdown'] = { - set : function(el, val) - { - console.log("hihihih") - $(this).easyDropDown('select',val) - //$(el).html(val); - } - }; -})(jQuery); - */ - - -/** (function ($) { var originalVal = $.fn.val; $.fn.val = function(value) { if (typeof value != 'undefined') { if($(this).data('easydropdown-select')) { - // setter invoked, do processing - $(this).easyDropDown('select',value); + $(this).easyDropDown('select',value, true); } return originalVal.call(this, value); } @@ -29,5 +12,4 @@ } }; })(jQuery); - */ diff --git a/web/app/assets/javascripts/landing/signup.js b/web/app/assets/javascripts/landing/signup.js index b0b006caa..a5f5a0f50 100644 --- a/web/app/assets/javascripts/landing/signup.js +++ b/web/app/assets/javascripts/landing/signup.js @@ -1,4 +1,4 @@ -(function() { +(function(context, $) { var signup = {} @@ -7,13 +7,13 @@ if(enable) { instrument_selector.removeAttr('style') - $('input', instrument_selector).removeAttr('disabled').removeAttr('style'); - $('select', instrument_selector).removeAttr('disabled').removeAttr('style'); + $('input', instrument_selector).removeAttr('disabled').removeAttr('style').easyDropDown('enable'); + $('select', instrument_selector).removeAttr('disabled').removeAttr('style').easyDropDown('enable'); } else { instrument_selector.css('color', '#AAA') - $('input', instrument_selector).attr('disabled', 'disabled').css('color', '#AAA'); - $('select', instrument_selector).attr('disabled', 'disabled').css('color', '#AAA'); + $('input', instrument_selector).attr('disabled', 'disabled').css('color', '#AAA').easyDropDown('disable'); + $('select', instrument_selector).attr('disabled', 'disabled').css('color', '#AAA').easyDropDown('disable'); } } @@ -40,12 +40,12 @@ var selected_country = $(this).val() if(selected_country) { // set region disabled while updating - region_select.attr('disabled', true); + region_select.attr('disabled', true).easyDropDown('disable'); $.ajax('/api/regions', { data : { country: selected_country }, dataType : 'json' - }).done(regions_done).fail(regions_fail).always(function() { region_select.attr('disabled', false) }) + }).done(regions_done).fail(regions_fail).always(function() { region_select.attr('disabled', false).easyDropDown('enable') }) } }) @@ -55,8 +55,12 @@ region_select.append("") $(data.regions).each(function(index, item) { - region_select.append("") + var option = $(''); + option.text(item).val(item); + region_select.append(option) }) + + context.JK.dropdown(region_select); } function regions_fail() { @@ -70,12 +74,12 @@ // only update if(selected_country && selected_region) { // set city disabled while updating - city_select.attr('disabled', true); + city_select.attr('disabled', true).easyDropDown('disable'); $.ajax('/api/cities', { data : { country: selected_country, region: selected_region }, dataType : 'json' - }).done(cities_done).fail(cities_fail).always(function() { city_select.attr('disabled', false) }) + }).done(cities_done).fail(cities_fail).always(function() { city_select.attr('disabled', false).easyDropDown('enable') }) } }) @@ -85,8 +89,12 @@ city_select.append("") $(data.cities).each(function(index, item) { - city_select.append("") + var option = $(''); + option.text(item).val(item); + city_select.append(option); }) + + context.JK.dropdown(city_select); } function cities_fail() { @@ -186,4 +194,4 @@ } window.signup = signup -})() \ No newline at end of file +})(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index 1fe7623c8..8db5501d2 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -468,6 +468,20 @@ }); } + context.JK.dropdown = function($select) { + + $select.each(function(index) { + var $item = $(this); + + if($item.data('easydropdown-select')) { + // if this has already been initialized, re-init it so it picks up any new + $item.easyDropDown('destroy') + } + $item.easyDropDown({nativeTouch: !gon.isNativeClient && gon.global.env != "test"}); + }) + + } + /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index 6ddfb5acb..cd3cc8fe0 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -1,12 +1,16 @@ //= require jquery +//= require jquery.monkeypatch //= require jquery_ujs //= require jquery.queryparams //= require jquery.hoverIntent //= require jquery.cookie //= require jquery.clipboard +//= require jquery.easydropdown //= require AAA_Log //= require AAC_underscore //= require globals +//= require AAB_message_factory +//= require AAC_underscore //= require facebook_helper //= require web/signupDialog //= require web/signinDialog @@ -16,6 +20,7 @@ //= require user_dropdown //= require jamkazam //= require utils +//= require custom_controls //= require ga //= require jam_rest //= require facebook_rest diff --git a/web/app/assets/stylesheets/client/account.css.scss b/web/app/assets/stylesheets/client/account.css.scss index c6410266f..41d66aced 100644 --- a/web/app/assets/stylesheets/client/account.css.scss +++ b/web/app/assets/stylesheets/client/account.css.scss @@ -73,18 +73,32 @@ margin-bottom:15px; } - .location { - position:relative; - padding-top:25px; - } - #account-change-avatar { height:13px; float:right; margin-right:17%; } + + .location { + position:relative; + padding-top:25px; + + .easydropdown-wrapper { + width:90%; + } + .easydropdown { + width:90%; + } + } + .birth_date { + .easydropdown{ + } + } + + .gender .easydropdown { + width:75px; } } @@ -101,12 +115,20 @@ height: 178px; overflow: auto; width: 100%; + + .easydropdown-wrapper { + width:100%; + } + + select, .easydropdown { + box-shadow: none !important; + color: #666666; + width: 100%; + box-sizing: border-box; + -moz-box-sizing:border-box; + } } - .profile-instrumentlist select { - box-shadow: none !important; - color: #666666; - width: 100%; - } + .account-sub-description { display: block; white-space: normal; @@ -133,6 +155,10 @@ div.field { margin-bottom:21px; + + label { + margin-bottom:2px; + } } div.profile-instrumentlist table { diff --git a/web/app/assets/stylesheets/client/band.css.scss b/web/app/assets/stylesheets/client/band.css.scss index 90952e2e1..7a310468e 100644 --- a/web/app/assets/stylesheets/client/band.css.scss +++ b/web/app/assets/stylesheets/client/band.css.scss @@ -321,3 +321,14 @@ height: 480px; width: 100%; } + +#band-setup-form { + .easydropdown { + padding: 0 3px; + width:100%; + } + + .easydropdown-wrapper { + width:80%; + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css index c31973f89..fb26f4c81 100644 --- a/web/app/assets/stylesheets/client/client.css +++ b/web/app/assets/stylesheets/client/client.css @@ -11,6 +11,8 @@ *= require_self *= require ./ie *= require jquery.bt + *= require easydropdown + *= require easydropdown_jk *= require ./jamkazam *= require ./content *= require ./paginator diff --git a/web/app/assets/stylesheets/client/createSession.css.scss b/web/app/assets/stylesheets/client/createSession.css.scss index 3d189bae2..64ecc7b57 100644 --- a/web/app/assets/stylesheets/client/createSession.css.scss +++ b/web/app/assets/stylesheets/client/createSession.css.scss @@ -14,11 +14,11 @@ .btn-choose-friends { margin:0; } -#create-session-genre select, #create-session-band select { +#create-session-genre .easydropdown, #create-session-band .easydropdown { min-width:140px; } -#find-session-genre select, #find-session-musician select { +#find-session-genre .easydropdown, #find-session-musician .easydropdown { width:145px; } diff --git a/web/app/assets/stylesheets/client/ftue.css.scss b/web/app/assets/stylesheets/client/ftue.css.scss index 02b4d1f27..1a582efc4 100644 --- a/web/app/assets/stylesheets/client/ftue.css.scss +++ b/web/app/assets/stylesheets/client/ftue.css.scss @@ -94,11 +94,11 @@ div.dialog.ftue { margin-top: 12px; } - ul { + .device_type ul { list-style:disc; } - li { + .device_type li { margin: 15px 12px 15px 36px; } @@ -113,6 +113,11 @@ div.dialog.ftue { p.intro { margin-top:0px; } + + .easydropdown-wrapper { + width:100%; + max-width:220px; + } .ftue-new { clear:both; position:relative; @@ -547,7 +552,7 @@ div[layout-id="ftue3"] { font-size:14px; } -.ftue-instrumentlist select { +.ftue-instrumentlist select, .ftue-instrumentlist .easydropdown { width:100%; color:#666; } diff --git a/web/app/assets/stylesheets/client/musician.css.scss b/web/app/assets/stylesheets/client/musician.css.scss index fffe5970b..cd97ac8c5 100644 --- a/web/app/assets/stylesheets/client/musician.css.scss +++ b/web/app/assets/stylesheets/client/musician.css.scss @@ -17,6 +17,11 @@ margin-top: 3px; padding-top: 3px; } + + + .easydropdown-wrapper { + float:left; + margin-left:2px; + } } diff --git a/web/app/assets/stylesheets/easydropdown_jk.css.scss b/web/app/assets/stylesheets/easydropdown_jk.css.scss new file mode 100644 index 000000000..e90fba225 --- /dev/null +++ b/web/app/assets/stylesheets/easydropdown_jk.css.scss @@ -0,0 +1,181 @@ +body.jam { + + .easydropdown-wrapper { + display:inline-block; + } + .dropdown-wrapper { + position:relative; + + .old { + display:none; + } + } + + .dropdown-wrappper div.dropdown-container { + width:auto; + } + + .dropdown-wrapper li{ + display: block; + font-size: 18px; + line-height: 1; + color: #000; + padding: 9px 12px; + overflow: hidden; + white-space: nowrap; + } + + + .dropdown-wrapper div.dropdown-container { + position: absolute; + height: 0; + left: -1px; + top: 100%; + margin-top: -1px; + background: #fff; + border: 1px solid #ccc; + border-top: 1px solid #eee; + border-radius: 0 0 3px 3px; + overflow: hidden; + opacity: 0; + min-width:100%; + } + + /* Height is adjusted by JS on open */ + + .dropdown-wrapper.open div.dropdown-container{ + opacity: 1; + z-index: 2; + } + + /* FADE OVERLAY FOR SCROLLING LISTS */ + + .dropdown-wrapper.scrollable div.dropdown-container::after{ + content: ''; + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 50px; + + box-shadow: inset 0 -50px 30px -35px #fff; + } + + .dropdown-wrapper.scrollable.bottom div.dropdown-container::after{ + opacity: 0; + } + + /* DROP DOWN LIST */ + + .dropdown-wrapper ul{ + position-wrapper: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + list-style: none; + overflow: hidden; + } + + .dropdown-wrapper.scrollable.open ul{ + overflow-y: auto; + } + + /* DROP DOWN LIST ITEMS */ + + .dropdown-wrapper li{ + list-style: none; + padding: 8px 12px; + } + + /* .focus class is also added on hover */ + + .dropdown-wrapper li.focus{ + background: #d24a67; + position: relative; + z-index: 3; + color: #fff; + } + + .dropdown-wrapper li.active{ + font-weight: 700; + } + + .dropdown-wrapper li { + padding: 5px 5px; + font-size:15px; + + color: #666666; + } + + .dropdown-wrapper li { + margin:0; + padding:3px; + font-size:15px; + color: #666666; + + &.focus { + background-color: #ed3618; + color:white; + } + } + + .dropdown-wrapper ul { + background-color: #C5C5C5; + margin-left:0; + border-color:#888888; + border-style:solid; + border-width: 1px 0 0 1px; + } +} + +body.jam div.dropdown { + + background-color: #C5C5C5; + box-shadow: 2px 2px 3px 0 #888888 inset; + border-radius: 6px; + border-width:0; + width:auto; + padding-right:20px; + + div.after { + box-shadow: 2px 2px 3px 0 #888888 inset; + } + div { + margin-top:2px; + } + + .selected { min-height: 15px; } + .selected, .dropdown li { + padding: 5px 5px; + font-size:15px; + + color: #666666; + } + .selected:after { + box-shadow: none; + } + + .carat { + right: 5px; + } + + li { + margin:0; + padding:3px; + font-size:15px; + color: #666666; + + &.focus { + background-color: #ed3618; + color:white; + } + } + ul { + background-color: #C5C5C5; + margin-left:0; + border-color:#888888; + border-style:solid; + border-width: 1px 0 0 1px; + } +} \ No newline at end of file diff --git a/web/app/assets/stylesheets/web/main.css.scss b/web/app/assets/stylesheets/web/main.css.scss index 657143247..f9e693c82 100644 --- a/web/app/assets/stylesheets/web/main.css.scss +++ b/web/app/assets/stylesheets/web/main.css.scss @@ -258,6 +258,17 @@ body.web { width:100%; } + .easydropdown-wrapper { + + width:100%; + + .easydropdown { + padding: 0 3px; + width:100%; + box-shadow: none !important; + } + } + .right-side { margin-left:25px; diff --git a/web/app/assets/stylesheets/web/web.css b/web/app/assets/stylesheets/web/web.css index 6b5779497..0f5f183bc 100644 --- a/web/app/assets/stylesheets/web/web.css +++ b/web/app/assets/stylesheets/web/web.css @@ -1,6 +1,8 @@ /** *= require client/ie *= require client/jamkazam +*= require easydropdown +*= require easydropdown_jk *= require client/screen_common *= require client/content *= require client/notify diff --git a/web/app/views/clients/_account_profile.html.erb b/web/app/views/clients/_account_profile.html.erb index 982493710..bf1ec484f 100644 --- a/web/app/views/clients/_account_profile.html.erb +++ b/web/app/views/clients/_account_profile.html.erb @@ -68,7 +68,7 @@
-
+
- +
@@ -49,8 +49,8 @@
Musician Access:
-
- @@ -66,8 +66,8 @@
Fan Access:
-
- diff --git a/web/app/views/clients/_ftue.html.erb b/web/app/views/clients/_ftue.html.erb index 4084acb51..db8f83be3 100644 --- a/web/app/views/clients/_ftue.html.erb +++ b/web/app/views/clients/_ftue.html.erb @@ -47,8 +47,8 @@
Frame
- + @@ -56,7 +56,7 @@
Buffer/In
- @@ -72,7 +72,7 @@
Buffer/Out
- @@ -194,7 +194,7 @@
Frame:
- @@ -203,7 +203,7 @@
Buffer/In:
- @@ -219,7 +219,7 @@
Buffer/Out:
- @@ -248,7 +248,7 @@ <%= image_tag "shared/icon_help.png", {:width => 12, :height => 12} %>
Audio Input: -
@@ -263,7 +263,7 @@ <%= image_tag "shared/icon_help.png", {:width => 12, :height => 12} %>
Voice Chat Input: -
@@ -278,7 +278,7 @@ <%= image_tag "shared/icon_help.png", {:width => 12, :height => 12} %>
Audio Output: -
diff --git a/web/app/views/clients/_genreSelector.html.erb b/web/app/views/clients/_genreSelector.html.erb index d63a04089..59e37c3be 100644 --- a/web/app/views/clients/_genreSelector.html.erb +++ b/web/app/views/clients/_genreSelector.html.erb @@ -1,3 +1,3 @@ - diff --git a/web/app/views/clients/_musician_filter.html.erb b/web/app/views/clients/_musician_filter.html.erb index f5650b65d..d70d3f7f7 100644 --- a/web/app/views/clients/_musician_filter.html.erb +++ b/web/app/views/clients/_musician_filter.html.erb @@ -1,7 +1,7 @@ <%= content_tag(:div, :class => 'filter-element wrapper foobar') do -%> <%= content_tag(:div, 'Filter By:', :class => 'filter-element desc') %> - <%= select_tag(:musician_order_by, options_for_select(Search::M_ORDERINGS), {:class => 'musician-order-by'} ) %> + <%= select_tag(:musician_order_by, options_for_select(Search::M_ORDERINGS), {:class => 'musician-order-by easydropdown'} ) %> <% end -%> <%= content_tag(:div, :class => "filter-element wrapper") do -%> <%= content_tag(:div, :class => 'filter-element wrapper') do -%> diff --git a/web/app/views/clients/_web_filter.html.erb b/web/app/views/clients/_web_filter.html.erb index a4c6d0ad6..9b0345848 100644 --- a/web/app/views/clients/_web_filter.html.erb +++ b/web/app/views/clients/_web_filter.html.erb @@ -12,12 +12,12 @@ <% if :feed == filter_label %> <%= content_tag(:div, 'Sort Feed by:', :class => 'filter-element desc') %> - <%= select_tag("#{filter_label}_order_by", options_for_select(Search::F_SORT_OPTS), {:class => "#{filter_label}-order-by"} ) %> + <%= select_tag("#{filter_label}_order_by", options_for_select(Search::F_SORT_OPTS), {:class => "#{filter_label}-order-by easydropdown" } ) %> <% else %> <%= content_tag(:div, 'Filter By:', :class => 'filter-element desc') %> - <%= select_tag("#{filter_label}_order_by", options_for_select(Search::ORDERINGS), {:class => "#{filter_label}-order-by"} ) %> + <%= select_tag("#{filter_label}_order_by", options_for_select(Search::ORDERINGS), {:class => "#{filter_label}-order-by easydropdown"} ) %> <% end %> <% end -%> @@ -26,18 +26,18 @@ <%= content_tag(:div, 'Instrument:', :class => 'filter-element desc') %> <%= select_tag("#{filter_label}_instrument", - options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] }))) %> + options_for_select([['Any', '']].concat(JamRuby::Instrument.all.collect { |ii| [ii.description, ii.id] })), {:class=> "easydropdown"}) %> <% elsif :band == filter_label %> <%= content_tag(:div, 'Genre:', :class => 'filter-element desc') %> <%= select_tag("#{filter_label}_genre", - options_for_select([['Any', '']].concat(JamRuby::Genre.all.collect { |ii| [ii.description, ii.id] }))) %> + options_for_select([['Any', '']].concat(JamRuby::Genre.all.collect { |ii| [ii.description, ii.id] })), {:class => 'easydropdown'}) %> <% elsif :feed == filter_label %> <%= content_tag(:div, 'Include Dates:', :class => 'filter-element desc') %> - <%= select_tag("#{filter_label}_date", options_for_select(Search::DATE_OPTS)) %> + <%= select_tag("#{filter_label}_date", options_for_select(Search::DATE_OPTS), {:class => "easydropdown"}) %> <% end %> <% end -%> @@ -45,14 +45,14 @@ <% if :feed == filter_label %> <%= content_tag(:div, 'Show:', :class => 'filter-element desc') %> - <%= select_tag("#{filter_label}_show", options_for_select(Search::SHOW_OPTS)) %> + <%= select_tag("#{filter_label}_show", options_for_select(Search::SHOW_OPTS), {:class => "easydropdown"}) %> <% else %> <%= content_tag(:div, 'Within', :class => 'filter-element desc') %> <%= content_tag(:div, :class => 'query-distance-params') do -%> <% default_distance = :musician == filter_label ? Search::M_MILES_DEFAULT : Search::B_MILES_DEFAULT %> - <%= select_tag("#{filter_label}_query_distance", options_for_select(Search::DISTANCE_OPTS, default_distance)) %> + <%= select_tag("#{filter_label}_query_distance", options_for_select(Search::DISTANCE_OPTS, default_distance), {:class => 'easydropdown'}) %> <% end -%> <%= content_tag(:div, :class => 'filter-element desc') do -%> miles of <%= content_tag(:span, current_user.current_city(request.remote_ip), :id => "#{filter_label}-filter-city") %> diff --git a/web/app/views/layouts/client.html.erb b/web/app/views/layouts/client.html.erb index 9257b476e..0f500f827 100644 --- a/web/app/views/layouts/client.html.erb +++ b/web/app/views/layouts/client.html.erb @@ -20,7 +20,7 @@ <%= render "layouts/social_meta" %> <% end %> - + <%= yield %> <%= render "shared/ga" %> diff --git a/web/app/views/layouts/corporate.html.erb b/web/app/views/layouts/corporate.html.erb index 0defc1ca1..a7016fcb3 100644 --- a/web/app/views/layouts/corporate.html.erb +++ b/web/app/views/layouts/corporate.html.erb @@ -18,7 +18,7 @@ <%= render "layouts/social_meta" %> <% end %> - +
diff --git a/web/app/views/layouts/landing.erb b/web/app/views/layouts/landing.erb index 6251a669f..1dca6a7dd 100644 --- a/web/app/views/layouts/landing.erb +++ b/web/app/views/layouts/landing.erb @@ -20,7 +20,7 @@ <%= render "layouts/social_meta" %> <% end %> - +
<%= javascript_include_tag "landing/landing" %> diff --git a/web/app/views/layouts/web.erb b/web/app/views/layouts/web.erb index 722f48c9b..605209531 100644 --- a/web/app/views/layouts/web.erb +++ b/web/app/views/layouts/web.erb @@ -20,7 +20,7 @@ <%= render "layouts/social_meta" %> <% end %> - + <%= javascript_include_tag "web/web" %> diff --git a/web/app/views/users/new.html.erb b/web/app/views/users/new.html.erb index f2e2a2755..7d613e655 100644 --- a/web/app/views/users/new.html.erb +++ b/web/app/views/users/new.html.erb @@ -36,7 +36,7 @@
<%= f.label :country, "Country:" %> - <% @countries.each do |country| %> <% unless country.blank? %> @@ -50,7 +50,7 @@
<%= f.label :state, "State/Province:" %> - <% @regions.each do |region| %> <% unless region.blank? %> @@ -63,7 +63,7 @@
<%= f.label :state, "City:" %> - <% @cities.each do |city| %> <% unless city.blank? %> @@ -105,7 +105,7 @@ _checkbox" name="jam_ruby_user[instruments][<%= instrument.id %>][selected]" type="checkbox"/><%= instrument.description %> - _proficiency" name="jam_ruby_user[instruments][<%= instrument.id %>][proficiency]" class='proficiency_selector easydropdown'> diff --git a/web/config/application.rb b/web/config/application.rb index 3fc0d980a..8d080b833 100644 --- a/web/config/application.rb +++ b/web/config/application.rb @@ -203,5 +203,7 @@ include JamRuby config.twitter_app_id = ENV['TWITTER_APP_ID'] || 'nQj2oEeoJZxECC33tiTuIg' config.twitter_app_secret = ENV['TWITTER_APP_SECRET'] || 'Azcy3QqfzYzn2fsojFPYXcn72yfwa0vG6wWDrZ3KT8' + + config.autocheck_create_session_agreement = false; end end diff --git a/web/config/environments/development.rb b/web/config/environments/development.rb index aa26582a7..548d9cb19 100644 --- a/web/config/environments/development.rb +++ b/web/config/environments/development.rb @@ -74,4 +74,7 @@ SampleApp::Application.configure do # this is so you can hardcode a source password in a client without having to retype it on every new session config.icecast_hardcoded_source_password = 'hackme' + + # set CREATE_SESSION_AGREEMENT=0 if you don't want the autoclick behavior + config.autocheck_create_session_agreement = ENV['CREATE_SESSION_AGREEMENT'] ? ENV['CREATE_SESSION_AGREEMENT'] == "1" : true end diff --git a/web/config/initializers/gon.rb b/web/config/initializers/gon.rb index 9a27929f4..7e4fa531e 100644 --- a/web/config/initializers/gon.rb +++ b/web/config/initializers/gon.rb @@ -1 +1,2 @@ -Gon.global.facebook_app_id = Rails.application.config.facebook_app_id \ No newline at end of file +Gon.global.facebook_app_id = Rails.application.config.facebook_app_id +Gon.global.env = Rails.env \ No newline at end of file diff --git a/web/spec/features/musician_search_spec.rb b/web/spec/features/musician_search_spec.rb index e7c29d7aa..4fe89d6c9 100644 --- a/web/spec/features/musician_search_spec.rb +++ b/web/spec/features/musician_search_spec.rb @@ -28,8 +28,11 @@ describe "Musician Search", :js => true, :type => :feature, :capybara_feature => end it "shows blank result set" do - expect(page).to have_selector('#musician_instrument') - find('#musician_instrument').find(:xpath, 'option[2]').select_option + wait_for_easydropdown('#musician_instrument') + # get the 2nd option from the instruments list + text = find('#musician_instrument', :visible => false).find(:xpath, 'option[2]', :visible => false).text + # and select it + jk_select(text, '#musician_instrument') expect(page).to_not have_selector('#musician-filter-results .musician-list-result') end diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb index 064b57ebd..9f8761adb 100644 --- a/web/spec/support/utilities.rb +++ b/web/spec/support/utilities.rb @@ -136,6 +136,16 @@ def get_description return description end +# will select the value from a easydropdown'ed select element +def jk_select(text, select) + + # the approach here is to find the hidden select element, and work way back up to the elements that need to be interacted with + find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]').trigger(:click) + find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open")]').find('li', text: text).trigger(:click) + + # works, but is 'cheating' because of visible = false + #select(genre, :from => 'genres', :visible => false) +end # takes, or creates, a unique session description which is returned for subsequent calls to join_session to use # in finding this session) @@ -153,7 +163,8 @@ def create_session(creator = FactoryGirl.create(:user), unique_session_desc = ni within('#create-session-form') do fill_in('description', :with => unique_session_desc) - select(genre, :from => 'genres') + #select(genre, :from => 'genres', :visible => false) # this works, but is 'cheating' because easydropdown hides the native select element + jk_select(genre, '#create-session-form select[name="genres"]') find('div.intellectual-property ins').trigger(:click) find('#btn-create-session').trigger(:click) # fails if page width is low end @@ -250,11 +261,11 @@ def set_session_as_public() end def get_options(selector) - return find(selector).all('option').collect(&:text).uniq + find(selector, :visible => false).all('option', :visible => false).collect(&:text).uniq end def selected_genres(selector='#session-settings-genre') - return page.evaluate_script("JK.GenreSelectorHelper.getSelectedGenres('#{selector}')") + page.evaluate_script("JK.GenreSelectorHelper.getSelectedGenres('#{selector}')") end def random_genre @@ -286,7 +297,7 @@ def change_session_genre #randomly just change it within('#session-settings-dialog') do wait_for_ajax @new_genre = get_options(here).-(["Select Genre"]).-(selected_genres).sample.to_s - select(@new_genre, :from => 'genres') + jk_select(@new_genre, '#session-settings-dialog select[name="genres"]') wait_for_ajax find('#session-settings-dialog-submit').trigger(:click) end @@ -324,4 +335,9 @@ end def show_user_menu page.execute_script("$('ul.shortcuts').show()") #page.execute_script("JK.UserDropdown.menuHoverIn()") +end + +# wait for the easydropdown version of the specified select element to become visible +def wait_for_easydropdown(select) + find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]') end \ No newline at end of file diff --git a/web/vendor/assets/javascripts/jquery.easydropdown.js b/web/vendor/assets/javascripts/jquery.easydropdown.js new file mode 100644 index 000000000..0133ea533 --- /dev/null +++ b/web/vendor/assets/javascripts/jquery.easydropdown.js @@ -0,0 +1,504 @@ +/* +* EASYDROPDOWN - A Drop-down Builder for Styleable Inputs and Menus +* Version: 2.1.4 +* License: Creative Commons Attribution 3.0 Unported - CC BY 3.0 +* http://creativecommons.org/licenses/by/3.0/ +* This software may be used freely on commercial and non-commercial projects with attribution to the author/copyright holder. +* Author: Patrick Kunka +* Copyright 2013 Patrick Kunka, All Rights Reserved +*/ + + +(function($){ + + function EasyDropDown(){ + this.isField = true, + this.down = false, + this.inFocus = false, + this.disabled = false, + this.cutOff = false, + this.hasLabel = false, + this.keyboardMode = false, + this.nativeTouch = true, + this.wrapperClass = 'dropdown easydropdown', + this.wrapperWrapperClass = 'easydropdown-wrapper', + this.onChange = null; + }; + + EasyDropDown.prototype = { + constructor: EasyDropDown, + instances: {}, + init: function(domNode, settings){ + var self = this; + + $.extend(self, settings); + self.$select = $(domNode); + self.$select.data('easydropdown-select', true) + self.id = domNode.id; + self.options = []; + self.$options = self.$select.find('option'); + self.isTouch = 'ontouchend' in document; + self.$select.removeClass(self.wrapperClass+' dropdown'); + if(self.$select.is(':disabled')){ + self.disabled = true; + }; + if(self.$options.length){ + self.$options.each(function(i){ + var $option = $(this); + if($option.is(':selected')){ + self.selected = { + index: i, + title: $option.text() + } + self.focusIndex = i; + }; + //if($option.hasClass('label') && i == 0){ + // self.hasLabel = true; + // self.label = $option.text(); + // $option.attr('value',''); + //} else { + self.options.push({ + domNode: $option[0], + title: $option.text(), + value: $option.val(), + selected: $option.is(':selected') + }); + //}; + }); + if(!self.selected){ + self.selected = { + index: 0, + title: self.$options.eq(0).text() + } + self.focusIndex = 0; + }; + self.render(); + }; + }, + + render: function(){ + var self = this, + touchClass = self.isTouch && self.nativeTouch ? ' touch' : '', + disabledClass = self.disabled ? ' disabled' : ''; + + self.$container = self.$select.wrap('
').parent().parent(); + + self.$containerWrapper = self.$container.wrap('').parent(); + + self.$active = $(''+self.selected.title+'').appendTo(self.$container); + self.$carat = $('').appendTo(self.$container); + //self.$scrollWrapper = $('
    ').appendTo(self.$container); + self.$scrollWrapper = $('').appendTo(self.$containerWrapper); + self.$dropDown = self.$scrollWrapper.find('ul'); + self.$form = self.$container.closest('form'); + $.each(self.options, function(){ + var option = this, + active = option.selected ? ' class="active"':''; + self.$dropDown.append(''+option.title+''); + }); + self.$items = self.$dropDown.find('li'); + + if(self.cutOff && self.$items.length > self.cutOff) { + self.$container.addClass('scrollable'); + self.$containerWrapper.addClass('scrollable'); + } + + self.getMaxHeight(); + + if(self.isTouch && self.nativeTouch){ + self.bindTouchHandlers(); + } else { + self.bindHandlers(); + }; + }, + + getMaxHeight: function(){ + var self = this; + + self.maxHeight = 0; + + for(i = 0; i < self.$items.length; i++){ + var $item = self.$items.eq(i); + self.maxHeight += $item.outerHeight(); + if(self.cutOff == i+1){ + break; + }; + }; + }, + + bindTouchHandlers: function(){ + var self = this; + self.$container.on('click.easyDropDown',function(){ + self.$select.focus(); + }); + self.$select.on({ + change: function(){ + var $selected = $(this).find('option:selected'), + title = $selected.text(), + value = $selected.val(); + + self.$active.text(title); + if(typeof self.onChange === 'function'){ + self.onChange.call(self.$select[0],{ + title: title, + value: value + }); + }; + }, + focus: function(){ + self.$container.addClass('focus'); + self.$containerWrapper.addClass('focus'); + }, + blur: function(){ + self.$container.removeClass('focus'); + self.$containerWrapper.removeClass('focus'); + } + }); + }, + + bindHandlers: function(){ + var self = this; + self.query = ''; + self.$container.on({ + 'click.easyDropDown': function(){ + if(!self.down && !self.disabled){ + self.open(); + } else { + self.close(); + }; + }, + 'mousemove.easyDropDown': function(){ + if(self.keyboardMode){ + self.keyboardMode = false; + }; + } + }); + + $('body').on('click.easyDropDown.'+self.id,function(e){ + var $target = $(e.target), + classNames = self.wrapperClass.split(' ').join('.'); + + if(!$target.closest('.'+classNames).length && self.down){ + self.close(); + }; + }); + + self.$items.on({ + 'click.easyDropDown': function(){ + var index = $(this).index(); + self.select(index); + self.$select.focus(); + }, + 'mouseover.easyDropDown': function(){ + if(!self.keyboardMode){ + var $t = $(this); + $t.addClass('focus').siblings().removeClass('focus'); + self.focusIndex = $t.index(); + }; + }, + 'mouseout.easyDropDown': function(){ + if(!self.keyboardMode){ + $(this).removeClass('focus'); + }; + } + }); + + self.$select.on({ + 'focus.easyDropDown': function(){ + self.$container.addClass('focus'); + self.inFocus = true; + }, + 'blur.easyDropDown': function(){ + self.$container.removeClass('focus'); + self.inFocus = false; + }, + 'keydown.easyDropDown': function(e){ + if(self.inFocus){ + self.keyboardMode = true; + var key = e.keyCode; + + if(key == 38 || key == 40 || key == 32){ + e.preventDefault(); + if(key == 38){ + self.focusIndex-- + self.focusIndex = self.focusIndex < 0 ? self.$items.length - 1 : self.focusIndex; + } else if(key == 40){ + self.focusIndex++ + self.focusIndex = self.focusIndex > self.$items.length - 1 ? 0 : self.focusIndex; + }; + if(!self.down){ + self.open(); + }; + self.$items.removeClass('focus').eq(self.focusIndex).addClass('focus'); + if(self.cutOff){ + self.scrollToView(); + }; + self.query = ''; + }; + if(self.down){ + if(key == 9 || key == 27){ + self.close(); + } else if(key == 13){ + e.preventDefault(); + self.select(self.focusIndex); + self.close(); + return false; + } else if(key == 8){ + e.preventDefault(); + self.query = self.query.slice(0,-1); + self.search(); + clearTimeout(self.resetQuery); + return false; + } else if(key != 38 && key != 40){ + var letter = String.fromCharCode(key); + self.query += letter; + self.search(); + clearTimeout(self.resetQuery); + }; + }; + }; + }, + 'keyup.easyDropDown': function(){ + self.resetQuery = setTimeout(function(){ + self.query = ''; + },1200); + } + }); + + self.$dropDown.on('scroll.easyDropDown',function(e){ + if(self.$dropDown[0].scrollTop >= self.$dropDown[0].scrollHeight - self.maxHeight){ + self.$container.addClass('bottom'); + self.$containerWrapper.addClass('bottom'); + } else { + self.$container.removeClass('bottom'); + self.$containerWrapper.removeClass('bottom'); + }; + }); + + if(self.$form.length){ + self.$form.on('reset.easyDropDown', function(){ + var active = self.hasLabel ? self.label : self.options[0].title; + self.$active.text(active); + }); + }; + }, + + unbindHandlers: function(){ + var self = this; + + self.$container + .add(self.$select) + .add(self.$items) + .add(self.$form) + .add(self.$dropDown) + .off('.easyDropDown'); + $('body').off('.'+self.id); + }, + + open: function(){ + var self = this, + scrollTop = window.scrollY || document.documentElement.scrollTop, + scrollLeft = window.scrollX || document.documentElement.scrollLeft, + scrollOffset = self.notInViewport(scrollTop); + + self.closeAll(); + self.getMaxHeight(); + self.$select.focus(); + window.scrollTo(scrollLeft, scrollTop+scrollOffset); + self.$container.addClass('open'); + self.$containerWrapper.addClass('open'); + self.$scrollWrapper.css('height',self.maxHeight+'px'); + self.down = true; + }, + + close: function(){ + var self = this; + self.$container.removeClass('open'); + self.$containerWrapper.removeClass('open'); + self.$scrollWrapper.css('height','0px'); + self.focusIndex = self.selected.index; + self.query = ''; + self.down = false; + }, + + closeAll: function(){ + var self = this, + instances = Object.getPrototypeOf(self).instances; + for(var key in instances){ + var instance = instances[key]; + instance.close(); + }; + }, + + select: function(index, noTrigger){ + var self = this; + + if(typeof index === 'string'){ + index = self.$select.find('option[value=\''+index+'\']').index(); + }; + + var option = self.options[index], + selectIndex = self.hasLabel ? index: index; + + if(!option) { return; } + self.$items.removeClass('active').eq(index).addClass('active'); + self.$active.text(option.title); + self.$select + .find('option') + .removeAttr('selected') + .eq(selectIndex) + .prop('selected',true) + + if(!noTrigger) { + self.$select.trigger('change'); + } + + self.selected = { + index: index, + title: option.title + }; + self.focusIndex = i; + if(typeof self.onChange === 'function'){ + self.onChange.call(self.$select[0],{ + title: option.title, + value: option.value + }); + }; + }, + + search: function(){ + var self = this, + lock = function(i){ + self.focusIndex = i; + self.$items.removeClass('focus').eq(self.focusIndex).addClass('focus'); + self.scrollToView(); + }, + getTitle = function(i){ + return self.options[i].title.toUpperCase(); + }; + + for(i = 0; i < self.options.length; i++){ + var title = getTitle(i); + if(title.indexOf(self.query) == 0){ + lock(i); + return; + }; + }; + + for(i = 0; i < self.options.length; i++){ + var title = getTitle(i); + if(title.indexOf(self.query) > -1){ + lock(i); + break; + }; + }; + }, + + scrollToView: function(){ + var self = this; + if(self.focusIndex >= self.cutOff){ + var $focusItem = self.$items.eq(self.focusIndex), + scroll = ($focusItem.outerHeight() * (self.focusIndex + 1)) - self.maxHeight; + + self.$dropDown.scrollTop(scroll); + }; + }, + + notInViewport: function(scrollTop){ + var self = this, + range = { + min: scrollTop, + max: scrollTop + (window.innerHeight || document.documentElement.clientHeight) + }, + menuBottom = self.$dropDown.offset().top + self.maxHeight; + + if(menuBottom >= range.min && menuBottom <= range.max){ + return 0; + } else { + return (menuBottom - range.max) + 5; + }; + }, + + destroy: function(){ + var self = this; + self.unbindHandlers(); + self.$select.unwrap().siblings().remove(); + self.$select.unwrap(); + delete Object.getPrototypeOf(self).instances[self.$select[0].id]; + }, + + disable: function(){ + var self = this; + self.disabled = true; + self.$container.addClass('disabled'); + self.$containerWrapper.addClass('disabled'); + self.$select.attr('disabled',true); + if(!self.down)self.close(); + }, + + enable: function(){ + var self = this; + self.disabled = false; + self.$container.removeClass('disabled'); + self.$containerWrapper.removeClass('disabled'); + self.$select.attr('disabled',false); + } + }; + + var instantiate = function(domNode, settings){ + domNode.id = !domNode.id ? 'EasyDropDown'+rand() : domNode.id; + var instance = new EasyDropDown(); + if(!instance.instances[domNode.id]){ + instance.instances[domNode.id] = instance; + instance.init(domNode, settings); + }; + }, + rand = function(){ + return ('00000'+(Math.random()*16777216<<0).toString(16)).substr(-6).toUpperCase(); + }; + + $.fn.easyDropDown = function(){ + var args = arguments, + dataReturn = [], + eachReturn; + + eachReturn = this.each(function(){ + if(args && typeof args[0] === 'string'){ + var item = EasyDropDown.prototype.instances[this.id]; + if(!item) { return; } + var data = item[args[0]](args[1], args[2], args[3]); + if(data)dataReturn.push(data); + } else { + instantiate(this, args[0]); + }; + }); + + if(dataReturn.length){ + return dataReturn.length > 1 ? dataReturn : dataReturn[0]; + } else { + return eachReturn; + }; + }; + + $(function(){ + if(typeof Object.getPrototypeOf !== 'function'){ + if(typeof 'test'.__proto__ === 'object'){ + Object.getPrototypeOf = function(object){ + return object.__proto__; + }; + } else { + Object.getPrototypeOf = function(object){ + return object.constructor.prototype; + }; + }; + }; + + $('select.dropdown').each(function(){ + var json = $(this).attr('data-settings'); + settings = json ? $.parseJSON(json) : {}; + instantiate(this, settings); + }); + }); + +})(jQuery); + diff --git a/web/vendor/assets/stylesheets/easydropdown.css b/web/vendor/assets/stylesheets/easydropdown.css new file mode 100644 index 000000000..d09ee1faa --- /dev/null +++ b/web/vendor/assets/stylesheets/easydropdown.css @@ -0,0 +1,204 @@ +/* --- EASYDROPDOWN DEFAULT THEME --- */ + +/* PREFIXED CSS */ + +.dropdown, +.dropdown div, +.dropdown li, +.dropdown div::after{ + -webkit-transition: all 150ms ease-in-out; + -moz-transition: all 150ms ease-in-out; + -ms-transition: all 150ms ease-in-out; + transition: all 150ms ease-in-out; +} + +.dropdown .selected::after, +.dropdown.scrollable div::after{ + -webkit-pointer-events: none; + -moz-pointer-events: none; + -ms-pointer-events: none; + pointer-events: none; +} + +/* WRAPPER */ + +.dropdown{ + position: relative; + width: 160px; + border: 1px solid #ccc; + cursor: pointer; + background: #fff; + + border-radius: 3px; + + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.dropdown.open{ + z-index: 2; +} + +.dropdown:hover{ + box-shadow: 0 0 5px rgba(0,0,0,.15); +} + +.dropdown.focus{ + box-shadow: 0 0 5px rgba(51,102,248,.4); +} + +/* CARAT */ + +.dropdown .carat{ + position: absolute; + right: 12px; + top: 50%; + margin-top: -4px; + border: 6px solid transparent; + border-top: 8px solid #000; +} + +.dropdown.open .carat{ + margin-top: -10px; + border-top: 6px solid transparent; + border-bottom: 8px solid #000; +} + +.dropdown.disabled .carat{ + border-top-color: #999; +} + +/* OLD SELECT (HIDDEN) */ + +.dropdown .old{ + position: absolute; + left: 0; + top: 0; + height: 0; + width: 0; + overflow: hidden; +} + +.dropdown select{ + position: absolute; + left: 0px; + top: 0px; +} + +.dropdown.touch .old{ + width: 100%; + height: 100%; +} + +.dropdown.touch select{ + width: 100%; + height: 100%; + opacity: 0; +} + +/* SELECTED FEEDBACK ITEM */ + +.dropdown .selected, +.dropdown li{ + display: block; + font-size: 18px; + line-height: 1; + color: #000; + padding: 9px 12px; + overflow: hidden; + white-space: nowrap; +} + +.dropdown.disabled .selected{ + color: #999; +} + +.dropdown .selected::after{ + content: ''; + position: absolute; + right: 0; + top: 0; + bottom: 0; + width: 60px; + + border-radius: 0 2px 2px 0; + box-shadow: inset -55px 0 25px -20px #fff; +} + +/* DROP DOWN WRAPPER */ + +.dropdown div{ + position: absolute; + height: 0; + left: -1px; + right: -1px; + top: 100%; + margin-top: -1px; + background: #fff; + border: 1px solid #ccc; + border-top: 1px solid #eee; + border-radius: 0 0 3px 3px; + overflow: hidden; + opacity: 0; +} + +/* Height is adjusted by JS on open */ + +.dropdown.open div{ + opacity: 1; + z-index: 2; +} + +/* FADE OVERLAY FOR SCROLLING LISTS */ + +.dropdown.scrollable div::after{ + content: ''; + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 50px; + + box-shadow: inset 0 -50px 30px -35px #fff; +} + +.dropdown.scrollable.bottom div::after{ + opacity: 0; +} + +/* DROP DOWN LIST */ + +.dropdown ul{ + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + list-style: none; + overflow: hidden; +} + +.dropdown.scrollable.open ul{ + overflow-y: auto; +} + +/* DROP DOWN LIST ITEMS */ + +.dropdown li{ + list-style: none; + padding: 8px 12px; +} + +/* .focus class is also added on hover */ + +.dropdown li.focus{ + background: #d24a67; + position: relative; + z-index: 3; + color: #fff; +} + +.dropdown li.active{ + font-weight: 700; +} \ No newline at end of file