From 5585502e2600844b0f5d464106db81cacfaeeb0c Mon Sep 17 00:00:00 2001 From: jlukic Date: Tue, 12 May 2015 18:45:13 -0400 Subject: [PATCH] Initial wiring of API to dropdown --- src/definitions/modules/dropdown.js | 174 +++++++++++++----- src/definitions/modules/dropdown.less | 74 +++++++- src/themes/default/modules/dropdown.variables | 21 ++- 3 files changed, 206 insertions(+), 63 deletions(-) diff --git a/src/definitions/modules/dropdown.js b/src/definitions/modules/dropdown.js index d34ea87c0..d336b780c 100644 --- a/src/definitions/modules/dropdown.js +++ b/src/definitions/modules/dropdown.js @@ -231,6 +231,18 @@ $.fn.dropdown = function(parameters) { }, setup: { + api: function() { + var + apiSettings = { + debug : settings.debug, + on : false, + action : 'select' + }, + searchHTML + ; + module.verbose('First request, initializing API'); + $module.api(apiSettings); + }, layout: function() { if( $module.is('select') ) { module.setup.select(); @@ -259,13 +271,7 @@ $.fn.dropdown = function(parameters) { module.debug('UI dropdown already exists. Creating dropdown menu only'); $module = $input.closest(selector.dropdown); $menu = $module.children(selector.menu); - if($menu.length === 0) { - $menu = $('
') - .addClass(className.menu) - .appendTo($module) - ; - } - $menu.html( templates.menu( selectValues )); + module.setup.menu(selectValues); } else { module.debug('Creating entire dropdown from select'); @@ -287,6 +293,15 @@ $.fn.dropdown = function(parameters) { } module.refresh(); }, + menu: function(values) { + if($menu.length === 0) { + $menu = $('
') + .addClass(className.menu) + .appendTo($module) + ; + } + $menu.html( templates.menu( values )); + }, reference: function() { var index = $allModules.index($module), @@ -508,22 +523,103 @@ $.fn.dropdown = function(parameters) { } }, - filter: function(searchTerm) { + filter: function(query) { var - $results = $(), - allItemsFiltered, - escapedTerm, - beginsWithRegExp - ; - searchTerm = (searchTerm !== undefined) - ? searchTerm - : module.get.query() + searchTerm = (query !== undefined) + ? query + : module.get.query(), + afterFiltered = function() { + if(module.is.multiple()) { + module.filterActive(); + } + module.select.firstUnfiltered(); + if( module.has.allResultsFiltered() ) { + if( settings.onNoResults.call(element, searchTerm) ) { + if(!settings.allowAdditions) { + module.verbose('All items filtered, showing message', searchTerm); + module.add.message(message.noResults); + } + } + else { + module.verbose('All items filtered, hiding dropdown', searchTerm); + module.hideMenu(); + } + } + else { + module.remove.message(); + } + } ; - escapedTerm = module.escape.regExp(searchTerm); - beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm'); if(module.has.maxSelections()) { return; } + if(false) { + // async + module.queryRemote(searchTerm, function() { + afterFiltered(); + }); + } + else { + // sync + module.filterItems(searchTerm); + afterFiltered(); + } + }, + + queryRemote: function(query, callback) { + var + apiSettings = { + mockResponseAsync: function(settings, callback) { + setTimeout(function() { + callback({ + success: true, + results: [ + { + name : 'Apple', + value : 'apple' + }, + { + name : 'Bear', + value : 'bear' + }, + { + name : 'Pineapple', + value : 'pineapple' + } + ] + }); + }, 300); + }, + onSuccess : function(response) { + module.setup.menu({ + values: response.results + }); + callback(); + }, + urlData: { + query: query + } + } + ; + if( !$module.api('get request') ) { + module.setup.api(); + } + $.extend(true, apiSettings, settings.apiSettings); + module.debug('Executing remote search', apiSettings); + $module + .api('abort') + .api('setting', apiSettings) + .api('query') + ; + }, + + filterItems: function(searchTerm) { + var + $results = $(), + escapedTerm = module.escape.regExp(searchTerm), + beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm') + ; + // avoid loop if we're matching nothing if(searchTerm === '') { $results = $item; } @@ -569,25 +665,6 @@ $.fn.dropdown = function(parameters) { .not($results) .addClass(className.filtered) ; - if(module.is.multiple()) { - module.filterActive(); - } - module.select.firstUnfiltered(); - if( module.has.allResultsFiltered() ) { - if( settings.onNoResults.call(element, searchTerm) ) { - if(!settings.allowAdditions) { - module.verbose('All items filtered, showing message', searchTerm); - module.add.message(message.noResults); - } - } - else { - module.verbose('All items filtered, hiding dropdown', searchTerm); - module.hideMenu(); - } - } - else { - module.remove.message(); - } }, fuzzySearch: function(query, term) { @@ -1631,6 +1708,9 @@ $.fn.dropdown = function(parameters) { $text.removeClass(className.filtered); } }, + loading: function() { + $module.addClass(className.loading); + }, placeholderText: function(text) { module.debug('Restoring placeholder text'); text = text || $module.data(metadata.placeholderText); @@ -1691,11 +1771,9 @@ $.fn.dropdown = function(parameters) { } module.debug('Scrolling to active item', offset); if(forceScroll || abovePage || belowPage) { - $menu - .scrollTop(offset) - .removeClass(className.loading) - ; + $menu.scrollTop(offset); } + $menu.removeClass(className.loading); } }, text: function(text) { @@ -2033,6 +2111,9 @@ $.fn.dropdown = function(parameters) { activeLabel: function() { $module.find(selector.label).removeClass(className.active); }, + loading: function() { + $module.removeClass(className.loading); + }, upward: function($menu) { var $element = $menu || $module; $element.removeClass(className.upward); @@ -2652,6 +2733,8 @@ $.fn.dropdown.settings = { on : 'click', // what event should show menu action on item selection action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){}) + apiSettings : {}, + keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing match : 'both', // what to match against with search selection (both, text, or label) @@ -2797,13 +2880,12 @@ $.fn.dropdown.settings.templates = { }, // generates just menu from select - menu: function(select) { + menu: function(response) { var - placeholder = select.placeholder || false, - values = select.values || {}, - html = '' + values = response.values || {}, + html = '' ; - $.each(select.values, function(index, option) { + $.each(response.values, function(index, option) { html += '
' + option.name + '
'; }); return html; diff --git a/src/definitions/modules/dropdown.less b/src/definitions/modules/dropdown.less index 1c57974d7..ecc729128 100755 --- a/src/definitions/modules/dropdown.less +++ b/src/definitions/modules/dropdown.less @@ -86,6 +86,7 @@ ---------------*/ .ui.dropdown > .dropdown.icon { + position: relative; width: auto; margin: @dropdownIconMargin; } @@ -499,13 +500,13 @@ select.ui.dropdown { } /* Visible Hover */ -.ui.selection.visible.dropdown:hover { - border-color: @selectionVisibleHoverBorderColor; - box-shadow: @selectionVisibleHoverBoxShadow; +.ui.selection.active.dropdown:hover { + border-color: @selectionActiveHoverBorderColor; + box-shadow: @selectionActiveHoverBoxShadow; } -.ui.selection.visible.dropdown:hover .menu { - border-color: @selectionVisibleHoverBorderColor; - box-shadow: @selectionVisibleHoverMenuBoxShadow; +.ui.selection.active.dropdown:hover .menu { + border-color: @selectionActiveHoverBorderColor; + box-shadow: @selectionActiveHoverMenuBoxShadow; } /* Dropdown Icon */ @@ -738,6 +739,59 @@ select.ui.dropdown { z-index: @hoveredZIndex; } +/*-------------------- + Loading +---------------------*/ + +/* Positioning */ +.ui.loading.dropdown > i.icon:before, +.ui.loading.dropdown > i.icon:after { + left: 30% !important; +} +.ui.loading.dropdown > i.icon { + top: 50% !important; +} +.ui.multiple.loading.dropdown > i.icon:before, +.ui.multiple.loading.dropdown > i.icon:after { + top: 0% !important; + left: 0% !important; +} + +.ui.loading.dropdown > i.icon:before { + position: absolute; + content: ''; + top: 50%; + left: 50%; + + margin: @loaderMargin; + width: @loaderSize; + height: @loaderSize; + + border-radius: @circularRadius; + border: @loaderLineWidth solid @loaderFillColor; +} +.ui.loading.dropdown > i.icon:after { + position: absolute; + content: ''; + top: 50%; + left: 50%; + + margin: @loaderMargin; + width: @loaderSize; + height: @loaderSize; + + animation: button-spin @loaderSpeed linear; + animation-iteration-count: infinite; + + border-radius: @circularRadius; + + border-color: @loaderLineColor transparent transparent; + border-style: solid; + border-width: @loaderLineWidth; + + box-shadow: 0px 0px 0px 1px transparent; +} + /*-------------------- @@ -944,11 +998,11 @@ select.ui.dropdown { } /* Visible Hover Upward */ -.ui.upward.selection.visible.dropdown:hover { - box-shadow: @upwardSelectionVisibleHoverBoxShadow; +.ui.upward.active.selection.dropdown:hover { + box-shadow: @upwardSelectionActiveHoverBoxShadow; } -.ui.upward.selection.visible.dropdown:hover .menu { - box-shadow: @upwardSelectionVisibleHoverMenuBoxShadow; +.ui.upward.active.selection.dropdown:hover .menu { + box-shadow: @upwardSelectionActiveHoverMenuBoxShadow; } /*-------------- diff --git a/src/themes/default/modules/dropdown.variables b/src/themes/default/modules/dropdown.variables index 76f13d1c0..46012bf51 100644 --- a/src/themes/default/modules/dropdown.variables +++ b/src/themes/default/modules/dropdown.variables @@ -7,6 +7,7 @@ --------------------*/ @transition: + box-shadow @defaultDuration @defaultEasing, width @defaultDuration @defaultEasing ; @borderRadius: @defaultBorderRadius; @@ -65,7 +66,7 @@ @subMenuRight: auto; @subMenuDistanceAway: -0.5em; @subMenuMargin: 0em 0em 0em @subMenuDistanceAway; -@subMenuBorderRadius: 0em @borderRadius @borderRadius 0em; +@subMenuBorderRadius: @borderRadius; @subMenuZIndex: 21; /* Menu Header */ @@ -197,9 +198,9 @@ @selectionVisibleMenuBoxShadow: @raisedShadow; /* Visible Hover */ -@selectionVisibleHoverBorderColor: @selectedBorderColor; -@selectionVisibleHoverBoxShadow: @selectionVisibleBoxShadow; -@selectionVisibleHoverMenuBoxShadow: @selectionVisibleMenuBoxShadow; +@selectionActiveHoverBorderColor: @selectedBorderColor; +@selectionActiveHoverBoxShadow: @selectionVisibleBoxShadow; +@selectionActiveHoverMenuBoxShadow: @selectionVisibleMenuBoxShadow; @selectionVisibleConnectingBorder: 0em; @selectionVisibleIconOpacity: 1; @@ -262,6 +263,12 @@ States --------------------*/ +/* Loading */ +@loaderSize: 1.2857em; +@loaderOffset: -(@loaderSize / 2); +@loaderMargin: @loaderOffset 0em 0em @loaderOffset; + + /* Hovered */ @hoveredItemBackground: @transparentBlack; @hoveredItemColor: @selectedTextColor; @@ -320,15 +327,15 @@ @upwardMenuBorderRadius: @borderRadius @borderRadius 0em 0em; @upwardSelectionHoverBoxShadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.05); @upwardSelectionVisibleBoxShadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.08); -@upwardSelectionVisibleHoverBoxShadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.05); -@upwardSelectionVisibleHoverMenuBoxShadow: 0px -2px 3px 0px rgba(0, 0, 0, 0.08); +@upwardSelectionActiveHoverBoxShadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.05); +@upwardSelectionActiveHoverMenuBoxShadow: 0px -2px 3px 0px rgba(0, 0, 0, 0.08); /* Flyout Direction */ @leftMenuDropdownIconFloat: left; @leftMenuDropdownIconMargin: @itemLineHeightOffset @itemElementDistance 0em 0em; /* Left */ -@leftSubMenuBorderRadius: @borderRadius 0em 0em @borderRadius; +@leftSubMenuBorderRadius: @borderRadius; /* Simple */ @simpleTransitionDuration: @defaultDuration;