Changes for page Solr Search
Last modified by Сергей Коршунов on 2025/12/29 15:30
From version 2.1
edited by Сергей Коршунов
on 2022/03/08 17:00
on 2022/03/08 17:00
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-search-solr-ui/14.1]
To version 8.1
edited by Сергей Коршунов
on 2025/12/29 15:30
on 2025/12/29 15:30
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-search-solr-ui/17.10.0]
Summary
-
Attachments (0 modified, 0 added, 4 removed)
-
Objects (2 modified, 0 added, 0 removed)
Details
- dark-grey-disclosure-arrow-down.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.admins - Size
-
... ... @@ -1,1 +1,0 @@ 1 -94 bytes - Content
- dark-grey-disclosure-arrow-left.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.admins - Size
-
... ... @@ -1,1 +1,0 @@ 1 -94 bytes - Content
- light-grey-disclosure-arrow-down.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.admins - Size
-
... ... @@ -1,1 +1,0 @@ 1 -94 bytes - Content
- light-grey-disclosure-arrow-left.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.admins - Size
-
... ... @@ -1,1 +1,0 @@ 1 -94 bytes - Content
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,11 +1,7 @@ 1 1 require(['jquery', 'xwiki-events-bridge'], function($) { 2 2 var enhanceSearchResultHighlights = function() { 3 - varhighlights = $(this).removeClass('hidden').parent().prev('.search-result-highlights').addClass('preview');3 + const highlights = $(this).removeClass('hidden').prev('.search-result-highlights').addClass('preview'); 4 4 5 - // Workaround for IE8 which doesn't support :first-of-type CSS selector. 6 - highlights.find('.search-result-highlight').first().addClass('first').parent('dd').addClass('first') 7 - .prev('dt').addClass('first'); 8 - 9 9 $(this).one('click', function(event) { 10 10 event.preventDefault(); 11 11 $(event.target).remove(); ... ... @@ -38,13 +38,26 @@ 38 38 }; 39 39 40 40 var addFacetValueCheckbox = function() { 41 - var checkBox = $(document.createElement('input')).attr('type', 'checkbox'); 37 + // Create an id unique to the facet value. 38 + let facetContainer = $(this).parents('.search-facet').first(); 39 + // We need the ids of the target facet elements to stay stable through the change, in order to refocus the item 40 + // that was clicked and triggered the change. 41 + // We use the JQuery index, so that id indexes are reset across facetContainers. 42 + // This allows for stable indexes: when reloading the facets after changing the filter for the target facet X, 43 + // the ids of all the checkbox for the target facet X will keep the same index. 44 + // This property is lost if multiple facets are changed in the query at once. 45 + $(this).attr('id', facetContainer.attr('data-name') + '-' + facetContainer.find('a.itemName').index($(this))); 46 + // Initialize the checkbox. 47 + let checkBox = $(document.createElement('input')).attr('type', 'checkbox'); 48 + checkBox.attr('aria-labelledby', $(this).attr('id')); 42 42 checkBox.prop('checked', $(this).hasClass('selected')); 43 43 // Add the 'checked' attribute so that it can be easily located with CSS. 44 44 checkBox.prop('checked') && checkBox.attr('checked', 'checked'); 45 45 checkBox.on('click', this.click.bind(this)); 46 - // Remove the 'selected' class because the selected state is marked using the check box. 47 - $(this).removeClass('selected').before(checkBox); 53 + // Remove the 'selected' class because the selected state is already marked using the check box. 54 + $(this).removeClass('selected') 55 + // Add the checkbox to the DOM 56 + $(this).before(checkBox) 48 48 }; 49 49 50 50 var enhanceSearchFacets = function() { ... ... @@ -61,8 +61,8 @@ 61 61 updateExpandCollapseAllFacetsState(facetsContainer); 62 62 63 63 // Expand/Collapse toggle for each facet. 64 - facetsContainer.find('. search-facet-header').on('click', function(event) {65 - $(event.target).parent('.search-facet').toggleClass('expanded'); 73 + facetsContainer.find('.facet-toggle').on('click', function(event) { 74 + $(event.target).parents('.search-facet').toggleClass('expanded'); 66 66 updateExpandCollapseAllFacetsState(facetsContainer); 67 67 }); 68 68 ... ... @@ -76,6 +76,11 @@ 76 76 var queryIndex = url.indexOf('?'); 77 77 return queryIndex < 0 ? '' : url.substr(queryIndex + 1); 78 78 }; 88 + 89 + let removeQueryString = function(url) { 90 + let queryIndex = url.indexOf('?'); 91 + return queryIndex < 0 ? url : url.substring(0, queryIndex); 92 + }; 79 79 80 80 var getSearchUIState = function() { 81 81 var expandedFacets = []; ... ... @@ -105,7 +105,9 @@ 105 105 106 106 var searchRequest = null; 107 107 108 - var pushSearchUIState = function(viewURL) { 122 + // changeTargetSelector is the CSS selector of the facet anchor that initiated this reload. ' 123 + // We expect the focus to go back to this place once the UI is reloaded. 124 + var pushSearchUIState = function(viewURL, changeTargetSelector) { 109 109 // If there is a request in progress, abort it to prevent its callback from being called. 110 110 searchRequest && searchRequest.abort(); 111 111 $('.search-ui').attr('aria-busy', true); ... ... @@ -118,6 +118,7 @@ 118 118 window.history.replaceState && window.history.replaceState(state, document.title); 119 119 // Make sure the browser address bar reflects the new state (and thus the new state can be bookmarked). 120 120 window.history.pushState && window.history.pushState(state, document.title, viewURL); 137 + document.querySelector(changeTargetSelector)?.focus(); 121 121 }); 122 122 }; 123 123 ... ... @@ -124,12 +124,12 @@ 124 124 var reloadSearchUI = function(event) { 125 125 event.preventDefault(); 126 126 var anchor = $(event.target).closest('a'); 127 - anchor.length && $(document).trigger('xwiki:search:update', anchor.attr('href'));144 + anchor.length && anchor.first().trigger('xwiki:search:update', anchor.attr('href')); 128 128 }; 129 129 130 130 // Others (e.g. a custom facet) can trigger a search UI update by firing this event. 131 131 $(document).on('xwiki:search:update', function(event, viewURL) { 132 - pushSearchUIState(viewURL); 149 + pushSearchUIState(viewURL, `[data-facetvalue='${CSS.escape(event.target.dataset.facetvalue)}']`); 133 133 }); 134 134 135 135 $(window).on('popstate', function(event) { ... ... @@ -169,10 +169,41 @@ 169 169 }); 170 170 171 171 var enhanceSearchUI = function() { 189 + // Enhance search options 190 + document.querySelectorAll('input.options-item').forEach(function (option){ 191 + option.addEventListener('change', function() { 192 + let queryFieldName = this.getAttribute('data-query-name'); 193 + let queryField = document.querySelector('input[name="' + queryFieldName + '"]'); 194 + queryField.value = this.checked ? 'true' : 'false'; 195 + // We want to build the URL the same way it's done in the velocimacro #extendQueryString 196 + // We retrieve the search parameters of the latest request 197 + let params = new URLSearchParams(window.location.search); 198 + let formParams = new URLSearchParams(new FormData(this.form)); 199 + // We replace the existing parameters with their value from the form 200 + for (let param of formParams.keys()) { 201 + if (params.has(param)) params.delete(param); 202 + for (let paramValue of formParams.getAll(param)) { 203 + params.append(param,paramValue); 204 + } 205 + } 206 + pushSearchUIState(window.location.pathname + '?' + params.toString(), 207 + 'input[data-query-name="' + queryFieldName + '"]'); 208 + }); 209 + }); 210 + // Enhance search result sorting 211 + document.querySelectorAll('.search-results-sort select#sort-by-input, ' + 212 + '.search-results-sort input#sort-order-input').forEach(function (sortInput){ 213 + sortInput.addEventListener('change', function() { 214 + let baseURL = removeQueryString(this.form.getAttribute('action')); 215 + pushSearchUIState(baseURL + "?" + 216 + new URLSearchParams(new FormData(this.form)).toString(), 217 + 'input[data-query-name="' + this.getAttribute('name') + '"]'); 218 + }); 219 + }); 220 + 172 172 $('.search-result-highlightAll').each(enhanceSearchResultHighlights); 173 173 $('.search-facets').each(enhanceSearchFacets); 174 174 $([ 175 - '.search-results-sort a.sort-item', 176 176 '.search-options a.options-item', 177 177 '.pagination a', 178 178 '.controlPagination a',
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -1,7 +1,7 @@ 1 1 #template('colorThemeInit.vm') 2 2 3 3 /* Hide the 'Created by', 'Modified by' and 'Tags' document sections. */ 4 -.xdocLastModification, .skin-colibri#document-info, #xdocFooter {4 +.xdocLastModification, #xdocFooter { 5 5 display: none; 6 6 } 7 7 #document-title > h1 { ... ... @@ -9,86 +9,99 @@ 9 9 margin-bottom: 0; 10 10 } 11 11 12 +/** 13 + * Layout for the search bar 14 + */ 15 +.search-bar { 16 + margin: .5em 0; 17 +} 18 + 19 +@media (min-width: 768px) { 20 + .search-bar { 21 + max-width: 50%; 22 + } 23 +} 24 + 12 12 /** 13 - * Searchform26 + * Layout for search controls (sort + options) 14 14 */ 15 15 16 -.skin-colibri .search-form { 17 - /* There is no space after the title in Colibri. */ 18 - margin-top: 1.5em; 29 +.search-results-controls { 30 + display: flex; 31 + flex-wrap: wrap; 32 + gap: 1em; 33 + 34 + & label { 35 + /* Reset the styles of the labels. */ 36 + margin: 0; 37 + font-weight: unset; 38 + } 19 19 } 20 20 21 -.skin-colibri .search-form input[type="search"] { 22 - /* Colibri doesn't have the grid system. */ 23 - width: 50%; 41 +.search-results-sort, 42 +.search-options, .search-options > ul, .search-options > ul > li, 43 +.search-options > ul > li > label { 44 + display: flex; 45 + gap: .4em; 46 + align-items: center; 24 24 } 25 25 26 26 /** 27 27 * Sort 28 28 */ 52 +/* This select should be especially lightweight on the UI. We're removing the default border and shadow. */ 53 +#sort-by-input { 54 + cursor: pointer; 29 29 30 -ul.search-results-sort { 31 - color: $theme.textSecondaryColor; 32 - font-size: .9em; 33 - padding: 5px 0 2px 0; 56 + &:hover, &:focus { 57 + cursor: pointer; 58 + } 59 +} 60 + 61 +/* This checkbox input should be styled as a switch between ascending and descending states. */ 62 +.search-results-sort #sort-order-input { 63 + /* Hide the default checkbox. We rely on the style of the icon in its label to make it work. */ 64 + appearance: none; 34 34 margin: 0; 35 35 } 36 -.search-results-sort li { 37 - display: inline; 38 - list-style-type: none; 39 - padding-left: 1.5em; 67 + 68 +#sort-by-input, .search-results-sort label:has(>#sort-order-input) { 69 + /* We want most of the styles from "form-control", but not the shadow that comes from bootstrap. */ 70 + box-shadow: none; 71 + & :hover,& :focus,& :focus-within { 72 + border-color: var(--input-border-focus); 73 + } 40 40 } 41 -.search-results-sort li:first-of-type { 42 - padding: 0; 75 + 76 +/* Flip the second icon so that it's the arrow going up and down. */ 77 +.search-results-sort label #sort-order-input + * + * { 78 + transform: scaleY(-1); 43 43 } 44 -a.sort-item { 45 - color: inherit; 46 - text-decoration: none; 80 + 81 +/* When the box is checked, we want to hide the first icon. 82 +When the box is not checked, we want to hide the second icon. */ 83 +.search-results-sort label #sort-order-input:checked + *, 84 +.search-results-sort label #sort-order-input:not(:checked) + * + * { 85 + display: none; 47 47 } 48 -a.sort-item:hover { 49 - color: $theme.linkColor; 50 - text-decoration: underline; 51 -} 52 -a.sort-item.active, a.sort-item.active:hover { 53 - font-weight: bold; 54 - color: $theme.textColor; 55 - text-decoration: none; 56 -} 57 -.sort-item-order { 58 - margin-left: .3em; 59 -} 60 60 61 61 /** 62 62 * Options 63 63 */ 64 64 65 -ul.search-options { 66 - color: $theme.textSecondaryColor; 67 - font-size: .9em; 68 - padding: 5px 0 2px 0; 92 +.search-options ul { 69 69 margin: 0; 70 -} 71 -.search-options li { 72 - display: inline; 73 - list-style-type: none; 74 - padding-left: 1.5em; 75 -} 76 -.search-options li:first-of-type { 77 77 padding: 0; 95 + 96 + & input[type="checkbox"] { 97 + position: unset; 98 + margin: 0; 99 + } 100 + 101 + & label { 102 + margin-right: 1em; 103 + } 78 78 } 79 -a.options-item { 80 - color: inherit; 81 - text-decoration: none; 82 -} 83 -a.options-item:hover { 84 - color: $theme.linkColor; 85 - text-decoration: underline; 86 -} 87 -a.options-item.active, a.options-item.active:hover{ 88 - font-weight: bold; 89 - color: $theme.textColor; 90 - text-decoration: none; 91 -} 92 92 93 93 /** 94 94 * Search Results ... ... @@ -98,12 +98,6 @@ 98 98 margin-top: 1em; 99 99 } 100 100 101 -/* Colibri skin doesn't have the grid system. */ 102 -.skin-colibri .search-results-left { 103 - margin: 0.5em 20em 0.5em 0; 104 - padding: 0.5em 0.5em 0.5em 0; 105 -} 106 - 107 107 .search-results { 108 108 padding: .3em 0 .8em 0; 109 109 } ... ... @@ -167,6 +167,8 @@ 167 167 168 168 dl.search-result-highlights > dt { 169 169 margin-top: .3em; 177 + color: var(--text-muted); 178 + font-weight: var(--font-weight-semibold); 170 170 } 171 171 172 172 blockquote.search-result-highlight { ... ... @@ -187,11 +187,6 @@ 187 187 font-weight: bold; 188 188 } 189 189 190 -dl.search-result-highlights > dt { 191 - color: $theme.textSecondaryColor; 192 - font-weight: normal; 193 -} 194 - 195 195 dl.search-result-highlights.preview dt, 196 196 dl.search-result-highlights.preview dd > * { 197 197 display: none; ... ... @@ -198,17 +198,10 @@ 198 198 } 199 199 200 200 dl.search-result-highlights.preview dt:first-of-type, 201 -dl.search-result-highlights.preview dd:first-of-type blockquote:first-of-type, 202 -/* Workaround for IE8 which doesn't support :first-of-type CSS selector. */ 203 -dl.search-result-highlights.preview dt.first, 204 -dl.search-result-highlights.preview dd.first blockquote.first { 205 +dl.search-result-highlights.preview dd:first-of-type blockquote:first-of-type { 205 205 display: block; 206 206 } 207 207 208 -a.search-result-highlightAll:after { 209 - content: ' \bb'; 210 -} 211 - 212 212 .search-result-debug { 213 213 white-space: pre; 214 214 } ... ... @@ -217,40 +217,23 @@ 217 217 * Facets 218 218 */ 219 219 220 -.search-facets { 221 - background-color: $theme.backgroundSecondaryColor; 222 - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); 223 - /* Leave space for the bottom shadow. */ 224 - margin-bottom: 1em; 225 - border-radius: 4px; 217 +.search-facets-header{ 218 + border-bottom: 1px solid var(--xwiki-border-color); 226 226 } 227 -/* Colibri skin doesn't have the grid system. */ 228 -.skin-colibri .search-facets { 229 - float: right; 230 - max-width: 19.5em; 231 - width: 19.5em; 232 -} 233 233 234 -.search-facets-header, 235 -.search-facets-actions, 236 -.search-facet { 237 - border-bottom: 1px solid $theme.borderColor; 238 - border-top: 1px solid $theme.pageContentBackgroundColor; 239 - position: relative; 221 +.search-facets-header strong { 222 + font-size: 1.25em; 240 240 } 241 241 242 242 .search-facets-header, 243 243 .search-facets-actions { 244 - padding: 0.5em1em;227 + padding: .5em 0; 245 245 } 229 + 246 246 .search-facet { 247 - padding: 0.5em.8em;231 + padding: .2em 0; 248 248 } 249 249 250 -.search-facets-header { 251 - border-top: none; 252 -} 253 - 254 254 .search-facets-header > p, 255 255 .search-facets-actions > p { 256 256 /* The wiki syntax generates paragraphs which have bottom margin. */ ... ... @@ -261,16 +261,6 @@ 261 261 font-size: .8em; 262 262 } 263 263 264 -.search-facets-actions a { 265 - color: $theme.textSecondaryColor; 266 - text-decoration: none; 267 -} 268 - 269 -.search-facets-actions a:hover { 270 - color: $theme.linkColor; 271 - text-decoration: underline; 272 -} 273 - 274 274 .search-facets-action-collapseAll, 275 275 .search-facets-action-expandAll { 276 276 float: right; ... ... @@ -282,64 +282,96 @@ 282 282 margin: 0; 283 283 } 284 284 285 -.search-facet:last-of-type { 286 - border-bottom: none; 255 +.search-facet-header, .search-facet-body { 256 + padding-left: .5em; 257 + border: 1px solid var(--xwiki-border-color); 258 + border-radius: var(--border-radius-small); 287 287 } 288 288 289 289 .search-facet-header { 290 - background: url("$doc.getAttachmentURL('dark-grey-disclosure-arrow-left.png')") no-repeat scroll 100% 50% transparent; 262 + background-color: var(--xwiki-background-secondary-color); 263 +} 264 + 265 +.search-facet-header label { 291 291 color: $theme.titleColor; 292 292 cursor: pointer; 293 - line-height: 1.4em; 294 - margin: 0 .2em; 268 + display: flex; 269 + justify-content: space-between; 270 + align-items: center; 295 295 } 296 296 297 -.search-facet-header:after { 298 - border-bottom: 1px dotted $theme.pageContentBackgroundColor; 299 - border-top: 1px dotted $theme.borderColor; 300 - clear: both; 301 - content: ""; 302 - display: block; 303 - height: 0; 304 - margin: 2.45em 0 0; 273 +.search-facet-body { 274 + opacity: 0; 275 + visibility: hidden; /* This makes sure the element is removed from the accessibility tree. */ 276 + 305 305 position: absolute; 306 - right: 0; 307 - top: 0; 308 - width: 100%; 278 + transform: translateY(-10px); /* Start the animation slightly above */ 279 + padding-top: .5em; 280 + 281 + border-top-width: 0; 282 + border-top-left-radius: 0; 283 + border-top-right-radius: 0; 309 309 } 310 310 311 -.search-facet:last-of-type .search-facet-header:after { 312 - border: medium none; 286 +.search-facet-body ul, 287 +.search-facet-body ol { 288 + font-size: .9em; 313 313 } 314 314 315 -.search-facet.expanded:last-of-type .search-facet-header:after { 316 - border-bottom: 1px dotted $theme.pageContentBackgroundColor; 317 - border-top: 1px dotted $theme.borderColor; 291 +.search-facet-body li { 292 + display: flex; 293 + flex-wrap: wrap; 294 + padding: .3em .5em; 318 318 } 319 319 320 -.search-facet-body { 321 - overflow: hidden; /* required for effect */ 322 - display: none; 323 - margin-top: .5em; 297 +.search-facet .search-facet-header .facet-toggle, button.facet-value-toggle { 298 + background: transparent; 299 + transition: background-color .2s ease-in-out; 324 324 } 325 325 326 -.search-facet-body ul, 327 -.search-facet-body ol { 328 - font-size: .9em; 302 +.search-facet .search-facet-header .facet-toggle:active, button.facet-value-toggle:active { 303 + box-shadow: unset; 329 329 } 330 330 331 -.search-facet-body li { 332 - padding: .1em .2em; 306 +.search-facet .search-facet-header .facet-toggle > span, button.facet-value-toggle > span, 307 +.search-facet .search-facet-header .facet-toggle > img, button.facet-value-toggle > img { 308 + transform: rotate(90deg); 333 333 } 334 334 335 -.search-facet.expanded .search-facet-header { 336 - background-image: url("$doc.getAttachmentURL('dark-grey-disclosure-arrow-down.png')"); 311 +.search-facet.expanded .search-facet-header .facet-toggle > span, .expanded > button.facet-value-toggle > span, 312 +.search-facet.expanded .search-facet-header .facet-toggle > img, .expanded > button.facet-value-toggle > img { 313 + transform: rotate(0deg); 337 337 } 338 338 339 -.search-facet.expanded .search-facet-body { 340 - display: block; 316 +@media (prefers-reduced-motion: no-preference) { 317 + .search-facet .search-facet-header .facet-toggle > span, button.facet-value-toggle > span, 318 + .search-facet .search-facet-header .facet-toggle > img, button.facet-value-toggle > img { 319 + transition: transform 0.2s ease; 320 + } 321 + 322 + .search-facet-body { 323 + transition: opacity 0.3s ease, transform 0.3s ease; 324 + } 341 341 } 342 342 327 +.search-facet.expanded { 328 + & .search-facet-header { 329 + border-bottom-width: 0; 330 + border-bottom-left-radius: 0; 331 + border-bottom-right-radius: 0; 332 + 333 + & label { 334 + font-weight: var(--font-weight-semibold); 335 + } 336 + } 337 + & .search-facet-body { 338 + opacity: 1; 339 + position: unset; /* This element should be positioned normally when shown. */ 340 + visibility: visible; 341 + transform: translateY(0); 342 + } 343 +} 344 + 343 343 .search-facet-body ul, .search-facet-body ul.users { 344 344 color: $theme.textSecondaryColor; 345 345 list-style: none; ... ... @@ -348,12 +348,7 @@ 348 348 margin: .5em 0; 349 349 } 350 350 351 -.search-facet-body li:hover { 352 - background-color: $theme.highlightColor; 353 -} 354 - 355 355 .search-facet-body input[type="checkbox"] { 356 - float: left; 357 357 margin: .2em 0; 358 358 } 359 359 ... ... @@ -366,7 +366,19 @@ 366 366 white-space: nowrap; 367 367 } 368 368 366 +/* Override the default style for links in content. */ 367 +body.content.preference-underlining-only-inline-links #xwikicontent .search-facet-body .itemName, 368 +body.content.preference-underlining-only-inline-links #xwikicontent .search-facet-body .more { 369 + text-decoration: none; 370 + /* Make sure we don't take over the default behaviour on hover with too much specificity. */ 371 + &:hover, &:focus { 372 + text-decoration: underline; 373 + } 374 +} 375 + 369 369 .search-facet-body .itemName, 377 +.search-facet-body .itemNameempty, 378 +.search-facet-body .facet-value-toggle, 370 370 .search-facet-body .more { 371 371 /* Remove link styling */ 372 372 color: $theme.textColor; ... ... @@ -384,8 +384,11 @@ 384 384 } 385 385 386 386 .search-facet-body .itemCount { 387 - float: right; 388 - padding: .1em 0; 396 + padding: .1em .5em; 397 + margin-left: auto; 398 + background-color: var(--nav-link-hover-bg); 399 + /* We want those item count blocks to be pill shaped. */ 400 + border-radius: 1em / 50%; 389 389 } 390 390 391 391 @media (max-width: 768px) { ... ... @@ -405,17 +405,6 @@ 405 405 } 406 406 407 407 /** 408 - * Fix the breadcrumb in Colibri skin. 409 - */ 410 -.skin-colibri .breadcrumb > li { 411 - display: inline; 412 -} 413 -.skin-colibri .breadcrumb > li + li:before { 414 - color: $theme.textSecondaryColor; 415 - content: ' \00BB '; 416 -} 417 - 418 -/** 419 419 * Miscellaneous 420 420 */ 421 421 ... ... @@ -424,13 +424,3 @@ 424 424 padding-left: 0; 425 425 } 426 426 427 -.paginationFilter .resultsNo, 428 -.paginationFilter .controlPagination, 429 -.paginationFilter .pagination { 430 - line-height: 22px; 431 -} 432 - 433 -.iconRSS { 434 - background: url("$xwiki.getSkinFile('icons/silk/feed.png')") no-repeat scroll 0 0 transparent; 435 - padding-left: 20px; 436 -}