| Conditions | 1 |
| Paths | 32 |
| Total Lines | 252 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | /** global: GLSR, jQuery */ |
||
| 2 | ;(function( _, wp, x ) { |
||
| 3 | |||
| 4 | 'use strict'; |
||
| 5 | |||
| 6 | var Search = function( selector, options ) { |
||
| 7 | this.el = x( selector ); |
||
| 8 | this.options = options; |
||
| 9 | this.searchTerm = null; |
||
| 10 | this.init_(); |
||
| 11 | }; |
||
| 12 | |||
| 13 | Search.prototype = { |
||
| 14 | defaults: { |
||
| 15 | action: null, |
||
| 16 | exclude: [], |
||
| 17 | onInit: null, |
||
| 18 | onResultClick: null, |
||
| 19 | results: {}, |
||
| 20 | selected: -1, |
||
| 21 | selectedClass: 'glsr-selected-result', |
||
| 22 | selectorEntries: '.glsr-strings-table tbody', |
||
| 23 | selectorResults: '.glsr-search-results', |
||
| 24 | selectorSearch: '.glsr-search-input', |
||
| 25 | // entriesEl |
||
| 26 | // resultsEl |
||
| 27 | // searchEl |
||
| 28 | }, |
||
| 29 | |||
| 30 | /** @return void */ |
||
| 31 | init_: function() { |
||
| 32 | this.options = x.extend( {}, this.defaults, this.options ); |
||
| 33 | if( !this.el.length )return; |
||
| 34 | this.options.entriesEl = this.el.parent().find( this.options.selectorEntries ); |
||
| 35 | this.options.resultsEl = this.el.find( this.options.selectorResults ); |
||
| 36 | this.options.searchEl = this.el.find( this.options.selectorSearch ); |
||
| 37 | this.options.searchEl.attr( 'aria-describedby', 'live-search-desc' ); |
||
| 38 | if( typeof this.options.onInit === 'function' ) { |
||
| 39 | this.options.onInit.call( this ); |
||
| 40 | } |
||
| 41 | this.initEvents_(); |
||
| 42 | }, |
||
| 43 | |||
| 44 | /** @return void */ |
||
| 45 | initEvents_: function() { |
||
| 46 | this.options.searchEl.on( 'input', _.debounce( this.onSearchInput_.bind( this ), 500 )); |
||
| 47 | this.options.searchEl.on( 'keyup', this.onSearchKeyup_.bind( this )); |
||
| 48 | this.options.searchEl.on( 'keydown keypress', function( ev ) { |
||
| 49 | if( GLSR.keys.ENTER !== ev.which )return; |
||
| 50 | ev.preventDefault(); |
||
| 51 | }); |
||
| 52 | x( document ).on( 'click', this.onDocumentClick_.bind( this )); |
||
| 53 | x( document ).on( 'keydown', this.onDocumentKeydown_.bind( this )); |
||
| 54 | }, |
||
| 55 | |||
| 56 | /** @return void */ |
||
| 57 | abort_: function() { |
||
| 58 | if( 'undefined' === typeof this.searchRequest )return; |
||
| 59 | this.searchRequest.abort(); |
||
| 60 | }, |
||
| 61 | |||
| 62 | /** @return void */ |
||
| 63 | clearResults_: function() { |
||
| 64 | this.abort_(); |
||
| 65 | this.options.resultsEl.empty(); |
||
| 66 | this.el.removeClass( 'is-active' ); |
||
| 67 | x( 'body' ).removeClass( 'glsr-focus' ); |
||
| 68 | }, |
||
| 69 | |||
| 70 | /** @return void */// Manage entries |
||
| 71 | deleteEntry_: function( index ) { |
||
| 72 | var row = this.options.entriesEl.children( 'tr' ).eq( index ); |
||
| 73 | var search = this; |
||
| 74 | row.find( 'td' ).css({ backgroundColor:'#faafaa' }); |
||
| 75 | row.fadeOut( 350, function() { |
||
| 76 | x( this ).remove(); |
||
| 77 | search.options.results = {}; |
||
| 78 | search.reindexRows_(); |
||
| 79 | search.setVisibility_(); |
||
| 80 | }); |
||
| 81 | }, |
||
| 82 | |||
| 83 | /** @return void */ |
||
| 84 | displayResults_: function( items ) { |
||
| 85 | x( 'body' ).addClass( 'glsr-focus' ); |
||
| 86 | this.options.resultsEl.append( items ); |
||
| 87 | this.options.resultsEl.children( 'span' ).on( 'click', this.onResultClick_.bind( this )); |
||
| 88 | }, |
||
| 89 | |||
| 90 | /** @return void */// Manage entries |
||
| 91 | makeSortable_: function() { |
||
| 92 | this.options.entriesEl.on( 'click', 'a.delete', this.onEntryDelete_.bind( this )); |
||
| 93 | this.options.entriesEl.sortable({ |
||
| 94 | items: 'tr', |
||
| 95 | tolerance: 'pointer', |
||
| 96 | start: function( ev, ui ) { |
||
| 97 | ui.placeholder.height( ui.helper[0].scrollHeight ); |
||
| 98 | }, |
||
| 99 | sort: function( ev, ui ) { |
||
| 100 | var top = ev.pageY - x( this ).offsetParent().offset().top - ( ui.helper.outerHeight( true ) / 2 ); |
||
| 101 | ui.helper.css({ |
||
| 102 | top: top + 'px', |
||
| 103 | }); |
||
| 104 | }, |
||
| 105 | }); |
||
| 106 | }, |
||
| 107 | |||
| 108 | /** @return void */ |
||
| 109 | navigateResults_: function( diff ) { |
||
| 110 | this.options.selected += diff; |
||
| 111 | this.options.results.removeClass( this.options.selectedClass ); |
||
| 112 | if( this.options.selected < 0 ) { |
||
| 113 | // reached the start (should now allow keydown scroll) |
||
| 114 | this.options.selected = -1; |
||
| 115 | this.options.searchEl.focus(); |
||
| 116 | } |
||
| 117 | if( this.options.selected >= this.options.results.length ) { |
||
| 118 | // reached the end (should now allow keydown scroll) |
||
| 119 | this.options.selected = this.options.results.length - 1; |
||
| 120 | } |
||
| 121 | if( this.options.selected >= 0 ) { |
||
| 122 | this.options.results.eq( this.options.selected ) |
||
| 123 | .addClass( this.options.selectedClass ) |
||
| 124 | .focus(); |
||
| 125 | } |
||
| 126 | }, |
||
| 127 | |||
| 128 | /** @return void */ |
||
| 129 | onDocumentClick_: function( ev ) { |
||
| 130 | if( x( ev.target ).find( this.el ).length && x( 'body' ).hasClass( 'glsr-focus' )) { |
||
| 131 | this.clearResults_(); |
||
| 132 | } |
||
| 133 | }, |
||
| 134 | |||
| 135 | /** @return void */ |
||
| 136 | onDocumentKeydown_: function( ev ) { |
||
| 137 | if( !this.options.results )return; |
||
| 138 | if( GLSR.keys.ESC === ev.which ) { |
||
| 139 | this.clearResults_(); |
||
| 140 | } |
||
| 141 | if( GLSR.keys.ENTER === ev.which || GLSR.keys.SPACE === ev.which ) { |
||
| 142 | var selected = this.options.resultsEl.find( '.' + this.options.selectedClass ); |
||
| 143 | if( selected ) { |
||
| 144 | selected.trigger( 'click' ); |
||
| 145 | } |
||
| 146 | } |
||
| 147 | if( GLSR.keys.UP === ev.which ) { |
||
| 148 | ev.preventDefault(); |
||
| 149 | this.navigateResults_(-1); |
||
| 150 | } |
||
| 151 | if( GLSR.keys.DOWN === ev.which ) { |
||
| 152 | ev.preventDefault(); |
||
| 153 | this.navigateResults_(1); |
||
| 154 | } |
||
| 155 | }, |
||
| 156 | |||
| 157 | /** @return void */// Manage entries |
||
| 158 | onEntryDelete_: function( ev ) { |
||
| 159 | ev.preventDefault(); |
||
| 160 | this.deleteEntry_( x( ev.target ).closest( 'tr' ).index() ); |
||
| 161 | }, |
||
| 162 | |||
| 163 | /** @return void */ |
||
| 164 | onResultClick_: function( ev ) { |
||
| 165 | ev.preventDefault(); |
||
| 166 | if( typeof this.options.onResultClick === 'function' ) { |
||
| 167 | this.options.onResultClick.call( this, ev ); |
||
| 168 | } |
||
| 169 | this.clearResults_(); |
||
| 170 | }, |
||
| 171 | |||
| 172 | /** @return void */ |
||
| 173 | onSearchInput_: function( ev ) { |
||
| 174 | this.abort_(); |
||
| 175 | if( this.searchTerm === ev.target.value && this.options.results.length ) { |
||
| 176 | return this.displayResults_( this.options.results ); |
||
| 177 | } |
||
| 178 | this.options.resultsEl.empty(); |
||
| 179 | this.options.selected = -1; |
||
| 180 | this.searchTerm = ev.target.value; |
||
| 181 | if( this.searchTerm === '' ) { |
||
| 182 | return this.reset_(); |
||
| 183 | } |
||
| 184 | this.el.addClass( 'is-active' ); |
||
| 185 | this.searchRequest = wp.ajax.post( GLSR.action, { |
||
| 186 | request: { |
||
| 187 | action: this.options.action, |
||
| 188 | exclude: this.options.exclude, |
||
| 189 | nonce: this.el.find( '#_search_nonce' ).val(), |
||
| 190 | search: this.searchTerm, |
||
| 191 | }, |
||
| 192 | }).done( function( response ) { |
||
| 193 | this.el.removeClass( 'is-active' ); |
||
| 194 | this.displayResults_( response.items ? response.items : response.empty ); |
||
| 195 | this.options.results = this.options.resultsEl.children(); |
||
| 196 | delete this.searchRequest; |
||
| 197 | }.bind( this )); |
||
| 198 | }, |
||
| 199 | |||
| 200 | /** @return void */ |
||
| 201 | onSearchKeyup_: function( ev ) { |
||
| 202 | if( GLSR.keys.ESC === ev.which ) { |
||
| 203 | this.reset_(); |
||
| 204 | } |
||
| 205 | if( GLSR.keys.ENTER === ev.which ) { |
||
| 206 | this.onSearchInput_( ev ); |
||
| 207 | ev.preventDefault(); |
||
| 208 | } |
||
| 209 | }, |
||
| 210 | |||
| 211 | /** @return void */// Manage entries |
||
| 212 | onUnassign: function( ev ) { |
||
| 213 | ev.preventDefault(); |
||
| 214 | var assigned = this.el.find( '.description' ); |
||
| 215 | this.el.find( 'input#assigned_to' ).val( '' ); |
||
| 216 | assigned.find( 'a' ).css({ color:'#c00' }); |
||
| 217 | assigned.fadeOut( 'fast', function() { |
||
| 218 | x( this ).html( '' ).show(); |
||
| 219 | }); |
||
| 220 | }, |
||
| 221 | |||
| 222 | /** @return void */// Manage entries |
||
| 223 | reindexRows_: function() { |
||
| 224 | var search = this; |
||
| 225 | this.options.exclude = []; |
||
| 226 | this.options.entriesEl.children( 'tr' ).each( function( index ) { |
||
| 227 | x( this ).find( '.glsr-string-td2' ).children().filter( ':input' ).each( function() { |
||
| 228 | var input = x( this ); |
||
| 229 | var name = input.attr( 'name' ).replace( /\[\d+\]/i, '[' + index + ']' ); |
||
| 230 | input.attr( 'name', name ); |
||
| 231 | if( input.is( '[data-id]' )) { |
||
| 232 | search.options.exclude.push({ id: input.val() }); |
||
| 233 | } |
||
| 234 | }); |
||
| 235 | }); |
||
| 236 | }, |
||
| 237 | |||
| 238 | /** @return void */ |
||
| 239 | reset_: function() { |
||
| 240 | this.clearResults_(); |
||
| 241 | this.options.results = {}; |
||
| 242 | this.options.searchEl.val( '' ); |
||
| 243 | }, |
||
| 244 | |||
| 245 | /** @return void */// Manage entries |
||
| 246 | setVisibility_: function() { |
||
| 247 | var action = this.options.entriesEl.children().length > 0 ? 'remove' : 'add'; |
||
| 248 | this.options.entriesEl.parent()[action + 'Class']( 'glsr-hidden' ); |
||
| 249 | }, |
||
| 250 | }; |
||
| 251 | |||
| 252 | GLSR.Search = Search; |
||
| 253 | })( window._, window.wp, jQuery ); |
||
| 254 |