diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index 9f73afcd2..91cc6c0f6 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -12,10 +12,10 @@ // //= require jquery //= require jquery_ujs +//= require jquery.icheck //= require jquery.color //= require jquery.cookie //= require jquery.Jcrop //= require jquery.naturalsize //= require jquery.queryparams -//= require bootstrap //= require_directory . diff --git a/web/app/assets/javascripts/createSession.js b/web/app/assets/javascripts/createSession.js index 303c31145..8dc0bdf24 100644 --- a/web/app/assets/javascripts/createSession.js +++ b/web/app/assets/javascripts/createSession.js @@ -374,6 +374,13 @@ resetForm(); } + // this exists solely due to a bug in Windows QTWebkit: https://bugreports.qt-project.org/browse/QTBUG-30072 + function initializeButtons() { + $('div[layout-id="createSession"] .iradiobuttons input').iCheck({ + checkboxClass: 'icheckbox_minimal', + radioClass: 'iradio_minimal' + }); + } function searchFriends(query) { if (query.length < 2) { $('#friend-search-results').empty(); @@ -409,6 +416,7 @@ events(); loadBands(); loadSessionSettings(); + initializeButtons(); var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow }; app.bindScreen('createSession', screenBindings); } diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css index 18f23a447..fd8e50ffa 100644 --- a/web/app/assets/stylesheets/client/client.css +++ b/web/app/assets/stylesheets/client/client.css @@ -35,4 +35,5 @@ *= require ./banner *= require ./clientUpdate *= require jquery.Jcrop + *= require icheck/minimal/minimal */ \ No newline at end of file diff --git a/web/app/assets/stylesheets/client/createSession.css.scss b/web/app/assets/stylesheets/client/createSession.css.scss index f85f04a0b..8bbd0c263 100644 --- a/web/app/assets/stylesheets/client/createSession.css.scss +++ b/web/app/assets/stylesheets/client/createSession.css.scss @@ -29,6 +29,7 @@ .radio-text { font-size:13px; + line-height:17px; } .friendbox { @@ -111,4 +112,20 @@ div.friendbox input[type=text] { padding:10px; border-bottom:solid 1px #999; cursor:pointer; -} \ No newline at end of file +} + + + +div[layout-id="createSession"] .iradiobuttons { + + margin-top:5px; + + div.iradio_minimal { + float:left; + } + + label { + float:left; + margin:0 10px 0 3px; + } +} diff --git a/web/app/assets/stylesheets/client/jquery-ui-overrides.css.scss b/web/app/assets/stylesheets/client/jquery-ui-overrides.css.scss new file mode 100644 index 000000000..e69de29bb diff --git a/web/app/views/clients/_createSession.html.erb b/web/app/views/clients/_createSession.html.erb index 00539f0d8..b8f5e6844 100644 --- a/web/app/views/clients/_createSession.html.erb +++ b/web/app/views/clients/_createSession.html.erb @@ -56,9 +56,9 @@ -
-  Open   -  By Approval +
+ +
@@ -73,9 +73,9 @@ -
-  Chat   -  No Fan Chat +
+ +
@@ -146,7 +146,7 @@
-
+
diff --git a/web/spec/features/avatar_spec.rb b/web/spec/features/avatar_spec.rb index 2261b5a2e..18aab6609 100644 --- a/web/spec/features/avatar_spec.rb +++ b/web/spec/features/avatar_spec.rb @@ -21,12 +21,13 @@ describe "Avatar", :js => true, :type => :feature, :capybara_feature => true do end it { - pending "capybara crashes trying this test" should have_selector('#account-edit-avatar-upload') - click_link "UPLOAD" # launch filepicker dialog, which is an iframe - within_frame('filepicker_dialog') { - attach_file('fileUpload', 'spec/assets/images/sample_avatar.png') - find('div.jcrop-tracker').should_not be_nil - } + + # this causes capybara 1.9.0 and 1.9.2 to crash. + #click_link "UPLOAD" # launch filepicker dialog, which is an iframe + #within_frame('filepicker_dialog') { + # attach_file('fileUpload', 'spec/assets/images/sample_avatar.png') + # find('div.jcrop-tracker').should_not be_nil + #} } end diff --git a/web/spec/features/find_sessions_spec.rb b/web/spec/features/find_sessions_spec.rb index 0551c54e6..2cd68738f 100644 --- a/web/spec/features/find_sessions_spec.rb +++ b/web/spec/features/find_sessions_spec.rb @@ -43,7 +43,7 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr within('#create-session-form') do fill_in('description', :with => @unique_session_desc) select('Rock', :from => 'genres') - check('intellectual-property') + find('intellectual-property').trigger(:click) click_link('btn-create-session') # fails if page width is low end diff --git a/web/spec/features/music_sessions_spec.rb b/web/spec/features/music_sessions_spec.rb index 99fbcae3d..cadf2c85c 100644 --- a/web/spec/features/music_sessions_spec.rb +++ b/web/spec/features/music_sessions_spec.rb @@ -9,7 +9,7 @@ describe "Music Session", :js => true, :type => :feature, :capybara_feature => t within('#create-session-form') do fill_in('description', :with => 'foobar') select('Ambient', :from => 'genres') - check('intellectual-property') + find('intellectual-property').trigger(:click) click_link('btn-create-session') end uu diff --git a/web/vendor/assets/images/icheck/minimal.png b/web/vendor/assets/images/icheck/minimal.png new file mode 100644 index 000000000..943be16fb Binary files /dev/null and b/web/vendor/assets/images/icheck/minimal.png differ diff --git a/web/vendor/assets/images/icheck/minimal@2x.png b/web/vendor/assets/images/icheck/minimal@2x.png new file mode 100644 index 000000000..d62291daa Binary files /dev/null and b/web/vendor/assets/images/icheck/minimal@2x.png differ diff --git a/web/vendor/assets/javascripts/jquery.icheck.js b/web/vendor/assets/javascripts/jquery.icheck.js new file mode 100644 index 000000000..d7d819da3 --- /dev/null +++ b/web/vendor/assets/javascripts/jquery.icheck.js @@ -0,0 +1,462 @@ +/*! + * iCheck v0.9.1, http://git.io/uhUPMA + * ================================= + * Powerful jQuery plugin for checkboxes and radio buttons customization + * + * (c) 2013 Damir Foy, http://damirfoy.com + * MIT Licensed + */ + +(function($) { + + // Cached vars + var _iCheck = 'iCheck', + _iCheckHelper = _iCheck + '-helper', + _checkbox = 'checkbox', + _radio = 'radio', + _checked = 'checked', + _unchecked = 'un' + _checked, + _disabled = 'disabled', + _determinate = 'determinate', + _indeterminate = 'in' + _determinate, + _update = 'update', + _type = 'type', + _click = 'click', + _touch = 'touchbegin.i touchend.i', + _add = 'addClass', + _remove = 'removeClass', + _callback = 'trigger', + _label = 'label', + _cursor = 'cursor', + _mobile = /ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent); + + // Plugin init + $.fn[_iCheck] = function(options, fire) { + + // Walker + var handle = ':' + _checkbox + ', :' + _radio, + stack = $(), + walker = function(object) { + object.each(function() { + var self = $(this); + + if (self.is(handle)) { + stack = stack.add(self); + } else { + stack = stack.add(self.find(handle)); + }; + }); + }; + + // Check if we should operate with some method + if (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(options)) { + + // Normalize method's name + options = options.toLowerCase(); + + // Find checkboxes and radio buttons + walker(this); + + return stack.each(function() { + if (options == 'destroy') { + tidy(this, 'ifDestroyed'); + } else { + operate($(this), true, options); + }; + + // Fire method's callback + if ($.isFunction(fire)) { + fire(); + }; + }); + + // Customization + } else if (typeof options == 'object' || !options) { + + // Check if any options were passed + var settings = $.extend({ + checkedClass: _checked, + disabledClass: _disabled, + indeterminateClass: _indeterminate, + labelHover: true + }, options), + + selector = settings.handle, + hoverClass = settings.hoverClass || 'hover', + focusClass = settings.focusClass || 'focus', + activeClass = settings.activeClass || 'active', + labelHover = !!settings.labelHover, + labelHoverClass = settings.labelHoverClass || 'hover', + + // Setup clickable area + area = ('' + settings.increaseArea).replace('%', '') | 0; + + // Selector limit + if (selector == _checkbox || selector == _radio) { + handle = ':' + selector; + }; + + // Clickable area limit + if (area < -50) { + area = -50; + }; + + // Walk around the selector + walker(this); + + return stack.each(function() { + + // If already customized + tidy(this); + + var self = $(this), + node = this, + id = node.id, + + // Layer styles + offset = -area + '%', + size = 100 + (area * 2) + '%', + layer = { + position: 'absolute', + top: offset, + left: offset, + display: 'block', + width: size, + height: size, + margin: 0, + padding: 0, + background: '#fff', + border: 0, + opacity: 0 + }, + + // Choose how to hide input + hide = _mobile ? { + position: 'absolute', + visibility: 'hidden' + } : area ? layer : { + position: 'absolute', + opacity: 0 + }, + + // Get proper class + className = node[_type] == _checkbox ? settings.checkboxClass || 'i' + _checkbox : settings.radioClass || 'i' + _radio, + + // Find assigned labels + label = $(_label + '[for="' + id + '"]').add(self.closest(_label)), + + // Wrap input + parent = self.wrap('
')[_callback]('ifCreated').parent().append(settings.insert), + + // Layer addition + helper = $('').css(layer).appendTo(parent); + + // Finalize customization + self.data(_iCheck, {o: settings, s: self.attr('style')}).css(hide); + !!settings.inheritClass && parent[_add](node.className); + !!settings.inheritID && id && parent.attr('id', _iCheck + '-' + id); + parent.css('position') == 'static' && parent.css('position', 'relative'); + operate(self, true, _update); + + // Label events + if (label.length) { + label.on(_click + '.i mouseenter.i mouseleave.i ' + _touch, function(event) { + var type = event[_type], + item = $(this); + + // Do nothing if input is disabled + if (!node[_disabled]) { + + // Click + if (type == _click) { + operate(self, false, true); + + // Hover state + } else if (labelHover) { + + // mouseleave|touchend + if (/ve|nd/.test(type)) { + parent[_remove](hoverClass); + item[_remove](labelHoverClass); + } else { + parent[_add](hoverClass); + item[_add](labelHoverClass); + }; + }; + + if (_mobile) { + event.stopPropagation(); + } else { + return false; + }; + }; + }); + }; + + // Input events + self.on(_click + '.i focus.i blur.i keyup.i keydown.i keypress.i', function(event) { + var type = event[_type], + key = event.keyCode; + + // Click + if (type == _click) { + return false; + + // Keydown + } else if (type == 'keydown' && key == 32) { + if (!(node[_type] == _radio && node[_checked])) { + if (node[_checked]) { + off(self, _checked); + } else { + on(self, _checked); + }; + }; + + return false; + + // Keyup + } else if (type == 'keyup' && node[_type] == _radio) { + !node[_checked] && on(self, _checked); + + // Focus/blur + } else if (/us|ur/.test(type)) { + parent[type == 'blur' ? _remove : _add](focusClass); + }; + }); + + // Helper events + helper.on(_click + ' mousedown mouseup mouseover mouseout ' + _touch, function(event) { + var type = event[_type], + + // mousedown|mouseup + toggle = /wn|up/.test(type) ? activeClass : hoverClass; + + // Do nothing if input is disabled + if (!node[_disabled]) { + + // Click + if (type == _click) { + operate(self, false, true); + + // Active and hover states + } else { + + // State is on + if (/wn|er|in/.test(type)) { + + // mousedown|mouseover|touchbegin + parent[_add](toggle); + + // State is off + } else { + parent[_remove](toggle + ' ' + activeClass); + }; + + // Label hover + if (label.length && labelHover && toggle == hoverClass) { + + // mouseout|touchend + label[/ut|nd/.test(type) ? _remove : _add](labelHoverClass); + }; + }; + + if (_mobile) { + event.stopPropagation(); + } else { + return false; + }; + }; + }); + }); + } else { + return this; + }; + }; + + // Do something with inputs + function operate(input, direct, method) { + var node = input[0]; + state = /er/.test(method) ? _indeterminate : /bl/.test(method) ? _disabled : _checked, + active = method == _update ? { + checked: node[_checked], + disabled: node[_disabled], + indeterminate: input.attr(_indeterminate) == 'true' || input.attr(_determinate) == 'false' + } : node[state]; + + // Check, disable or indeterminate + if (/^(ch|di|in)/.test(method) && !active) { + on(input, state); + + // Uncheck, enable or determinate + } else if (/^(un|en|de)/.test(method) && active) { + off(input, state); + + // Update + } else if (method == _update) { + + // Handle states + for (var state in active) { + if (active[state]) { + on(input, state, true); + } else { + off(input, state, true); + }; + }; + + } else if (!direct || method == 'toggle') { + + // Helper or label was clicked + if (!direct) { + input[_callback]('ifClicked'); + }; + + // Toggle checked state + if (active) { + if (node[_type] !== _radio) { + off(input, state); + }; + } else { + on(input, state); + }; + }; + }; + + // Add checked, disabled or indeterminate state + function on(input, state, keep) { + var node = input[0], + parent = input.parent(), + checked = state == _checked, + indeterminate = state == _indeterminate, + callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled', + regular = option(node, callback + capitalize(node[_type])), + specific = option(node, state + capitalize(node[_type])); + + // Prevent unnecessary actions + if (node[state] !== true) { + + // Toggle assigned radio buttons + if (!keep && state == _checked && node[_type] == _radio && node.name) { + var form = input.closest('form'), + inputs = 'input[name="' + node.name + '"]'; + + inputs = form.length ? form.find(inputs) : $(inputs); + + inputs.each(function() { + if (this !== node && $.data(this, _iCheck)) { + off($(this), state); + }; + }); + }; + + // Indeterminate state + if (indeterminate) { + + // Add indeterminate state + node[state] = true; + + // Remove checked state + if (node[_checked]) { + off(input, _checked, 'force'); + }; + + // Checked or disabled state + } else { + + // Add checked or disabled state + if (!keep) { + node[state] = true; + }; + + // Remove indeterminate state + if (checked && node[_indeterminate]) { + off(input, _indeterminate, false); + }; + }; + + // Trigger callbacks + callbacks(input, checked, state, keep); + }; + + // Add proper cursor + if (node[_disabled] && !!option(node, _cursor, true)) { + parent.find('.' + _iCheckHelper).css(_cursor, 'default'); + }; + + // Add state class + parent[_add](specific || option(node, state)); + + // Remove regular state class + parent[_remove](regular || option(node, callback) || ''); + }; + + // Remove checked, disabled or indeterminate state + function off(input, state, keep) { + var node = input[0], + parent = input.parent(), + checked = state == _checked, + indeterminate = state == _indeterminate, + callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled', + regular = option(node, callback + capitalize(node[_type])), + specific = option(node, state + capitalize(node[_type])); + + // Prevent unnecessary actions + if (node[state] !== false) { + + // Toggle state + if (indeterminate || !keep || keep == 'force') { + node[state] = false; + }; + + // Trigger callbacks + callbacks(input, checked, callback, keep); + }; + + // Add proper cursor + if (!node[_disabled] && !!option(node, _cursor, true)) { + parent.find('.' + _iCheckHelper).css(_cursor, 'pointer'); + }; + + // Remove state class + parent[_remove](specific || option(node, state) || ''); + + // Add regular state class + parent[_add](regular || option(node, callback)); + }; + + // Remove all traces + function tidy(node, callback) { + if ($.data(node, _iCheck)) { + var input = $(node); + + // Remove everything except input + input.parent().html(input.attr('style', $.data(node, _iCheck).s || '')[_callback](callback || '')); + + // Unbind events + input.off('.i').unwrap(); + $(_label + '[for="' + node.id + '"]').add(input.closest(_label)).off('.i'); + }; + }; + + // Get some option + function option(node, state, regular) { + if ($.data(node, _iCheck)) { + return $.data(node, _iCheck).o[state + (regular ? '' : 'Class')]; + }; + }; + + // Capitalize some string + function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }; + + // Executable handlers + function callbacks(input, checked, callback, keep) { + if (!keep) { + if (checked) { + input[_callback]('ifToggled'); + }; + + input[_callback]('ifChanged')[_callback]('if' + capitalize(callback)); + }; + }; +})(jQuery); diff --git a/web/vendor/assets/stylesheets/icheck/minimal/minimal.css b/web/vendor/assets/stylesheets/icheck/minimal/minimal.css new file mode 100644 index 000000000..fea9c54f1 --- /dev/null +++ b/web/vendor/assets/stylesheets/icheck/minimal/minimal.css @@ -0,0 +1,60 @@ +/* iCheck plugin Minimal skin, black +----------------------------------- */ +.icheckbox_minimal, +.iradio_minimal { + display: block; + margin: 0; + padding: 0; + width: 18px; + height: 18px; + background: url(/assets/icheck/jamkazam.png) no-repeat; + border: none; + cursor: pointer; +} + +.icheckbox_minimal { + background-position: 0 0; +} + .icheckbox_minimal.hover { + background-position: -20px 0; + } + .icheckbox_minimal.checked { + background-position: -40px 0; + } + .icheckbox_minimal.disabled { + background-position: -60px 0; + cursor: default; + } + .icheckbox_minimal.checked.disabled { + background-position: -80px 0; + } + +.iradio_minimal { + background-position: -100px 0; +} + .iradio_minimal.hover { + background-position: -120px 0; + } + .iradio_minimal.checked { + background-position: -140px 0; + } + .iradio_minimal.disabled { + background-position: -160px 0; + cursor: default; + } + .iradio_minimal.checked.disabled { + background-position: -180px 0; + } + +/* Retina support */ +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), + only screen and (-moz-min-device-pixel-ratio: 1.5), + only screen and (-o-min-device-pixel-ratio: 3/2), + only screen and (min-device-pixel-ratio: 1.5) { + .icheckbox_minimal, + .iradio_minimal { + background-image: url(/assets/icheck/jamkazam@2x.png); + -webkit-background-size: 200px 20px; + background-size: 200px 20px; + } +} \ No newline at end of file