1 2;(function($, undefined) 3{ 4 /* 5 * undefined is used here as the undefined global variable in ECMAScript 3 is mutable (i.e. it can 6 * be changed by someone else). undefined isn't really being passed in so we can ensure that its value is 7 * truly undefined. In ES5, undefined can no longer be modified. 8 */ 9 10 /** 11 * Enable agenda scrolling 12 * @param object options - optional (see defaults for a complete list) 13 */ 14 $.fn.scrollAgenda = function(options) 15 { 16 // Settings 17 var globalSettings = $.extend({}, $.fn.scrollAgenda.defaults, options); 18 19 this.each(function(i) 20 { 21 // Agenda 22 var agenda = $(this).closest('.agenda').addClass('scrolling-agenda'), 23 24 // Options 25 settings = $.extend({}, globalSettings, agenda.data('agenda-options')), 26 27 // Events columns 28 columns = agenda.children('.agenda-wrapper').children('.agenda-events'), 29 nbColumns = columns.length, 30 31 // Size & number of visible columns 32 colSize, colCount = -1, 33 34 // Visible columns range 35 range = [-1, -1], 36 37 // Functions 38 refreshColumns, setFirstColumn, scrollPrevious, scrollNext; 39 40 // Check if valid 41 if (nbColumns < 1) 42 { 43 return; 44 } 45 46 // Create scroll arrows 47 columns.children('.agenda-header').each(function(i) 48 { 49 var header = $(this); 50 51 // Previous 52 if (i > 0 && header.children('.agenda-previous').length === 0) 53 { 54 $('<a href="#" title="'+settings.prevTitle+'" class="agenda-previous"><span class="icon-left-round"></span></a>').prependTo(header).applySetup(); 55 } 56 57 // Next 58 if (i < nbColumns-1 && header.children('.agenda-next').length === 0) 59 { 60 $('<a href="#" title="'+settings.nextTitle+'" class="agenda-next"><span class="icon-right-round"></span></a>').prependTo(header).applySetup(); 61 } 62 }); 63 64 // Behavior 65 agenda.on('click', '.agenda-previous', function(event) 66 { 67 event.preventDefault(); 68 69 // If scrolling 70 if (scrollPrevious()) 71 { 72 return; 73 } 74 75 }).on('click', '.agenda-next', function(event) 76 { 77 event.preventDefault(); 78 79 // If scrolling 80 if (scrollNext()) 81 { 82 return; 83 } 84 }); 85 86 // Set first visible column 87 columns.eq(settings.first).addClass('agenda-visible-column'); 88 89 // Function to refresh visible columns 90 refreshColumns = function() 91 { 92 var firstCol, 93 oldCount = colCount; 94 95 // Mode 96 if (settings.auto) 97 { 98 colCount = Math.max(1, Math.floor(agenda.width()/settings.minWidth)); 99 } 100 else 101 { 102 colCount = settings.columns; 103 } 104 105 // Column size 106 colSize = 100/colCount; 107 108 // First visible column 109 firstCol = columns.filter('.agenda-visible-column:first'); 110 if (firstCol.length === 0) 111 { 112 // Not active yet, get first one 113 firstCol = columns.eq(0); 114 } 115 else 116 { 117 // Check if enough columns to fill slots 118 if (firstCol.nextAll('.agenda-events').length < colCount-1) 119 { 120 firstCol = columns.eq(-colCount); 121 } 122 } 123 124 // If size change 125 if (colCount !== oldCount && settings.onSizeChange) 126 { 127 settings.onSizeChange.call(agenda[0], colCount); 128 } 129 130 // Refresh 131 setFirstColumn(firstCol, false); 132 }; 133 134 // Set first column, and position others 135 setFirstColumn = function(firstCol, animate) 136 { 137 var oldRangeStart = range[0], 138 oldRangeEnd = range[1], 139 prevCols; 140 141 // firstCol argument type 142 if (typeof firstCol === 'number') 143 { 144 firstCol = columns.eq(firstCol); 145 } 146 else if (typeof firstCol === 'string') 147 { 148 firstCol = columns.filter(firstCol); 149 } 150 151 // Animate argument 152 if (animate == undefined || animate === null) 153 { 154 animate = settings.animate; 155 } 156 157 // Check validity 158 if (!(firstCol instanceof jQuery) || firstCol.length === 0) 159 { 160 return; 161 } 162 163 // Trim 164 firstCol = firstCol.first(); 165 166 // Init 167 firstCol.addClass('agenda-visible-column agenda-visible-first').stop(true)[animate ? 'animate' : 'css']({ 168 left: '0%', 169 right: (100-colSize)+'%', 170 marginLeft: '-1px' // This is to hide left border 171 }); 172 firstCol[(colCount === 1) ? 'addClass' : 'removeClass']('agenda-visible-last'); 173 174 // Previous columns 175 prevCols = firstCol.prevAll('.agenda-events'); 176 prevCols.removeClass('agenda-visible-column agenda-visible-first agenda-visible-last').each(function(i) 177 { 178 var column = $(this); 179 180 // Position 181 column.stop(true)[animate ? 'animate' : 'css']({ 182 left: (-colSize*(i+1))+'%', 183 right: (100+(colSize*i))+'%', 184 marginLeft: '0px' 185 });
186 }); 187 188 // Next columns 189 firstCol.nextAll('.agenda-events').removeClass('agenda-visible-first').each(function(i) 190 { 191 var column = $(this); 192 193 // Visible class 194 column[(i < colCount-1) ? 'addClass' : 'removeClass']('agenda-visible-column'); 195 column[(i === colCount-2) ? 'addClass' : 'removeClass']('agenda-visible-last'); 196 197 // Position 198 column.stop(true)[animate ? 'animate' : 'css']({ 199 left: (colSize*(i+1))+'%', 200 right: (100-(colSize*(i+2)))+'%', 201 marginLeft: '0px' 202 }); 203 }); 204 205 // Update range 206 range = [prevCols.length, prevCols.length+colCount-1]; 207 208 // Detect range change 209 if ((oldRangeStart != range[0] || oldRangeEnd != range[1]) && settings.onRangeChange) 210 { 211 settings.onRangeChange.call(agenda[0], range[0], range[1]); 212 } 213 }; 214 215 // First setup 216 refreshColumns(); 217 218 // Watch size change 219 agenda.widthchange(refreshColumns); 220 221 // Function to scroll to previous column 222 scrollPrevious = function() 223 { 224 var prev, firstCol; 225 226 // First visible column 227 firstCol = columns.filter('.agenda-visible-column:first'); 228 if (firstCol.length === 0) 229 { 230 firstCol = columns.eq(0); 231 } 232 233 // Is there a previous column? 234 prev = firstCol.prev('.agenda-events'); 235 if (prev.length > 0) 236 { 237 setFirstColumn(prev, settings.animate); 238 return true; 239 } 240 241 return false; 242 }; 243 244 // Function to scroll to next column 245 scrollNext = function() 246 { 247 var next, firstCol; 248 249 // First visible column 250 firstCol = columns.filter('.agenda-visible-column:first'); 251 if (firstCol.length === 0) 252 { 253 firstCol = columns.eq(0); 254 } 255 256 // Is there a enough columns to scroll? 257 next = firstCol.nextAll('.agenda-events'); 258 if (next.length >= colCount) 259 { 260 setFirstColumn(next.first(), settings.animate); 261 return true; 262 } 263 264 return false; 265 }; 266 267 // Interface 268 agenda.data('agenda', { 269 setFirstColumn: setFirstColumn, 270 scrollPrevious: scrollPrevious, 271 scrollNext: scrollNext 272 }); 273 }); 274 275 return this; 276 }; 277 278 /** 279 * Set the first visible column 280 * @param int|string|jQuery firstCol either an index (starting from 0), an CSS selector or a jQuery object 281 * @param boolean|null animate true to animate the movement, false to disable animation, null to use settings value (optional, default: null) 282 */ 283 $.fn.scrollAgendaFirstColumn = function(firstCol, animate) 284 { 285 return this.each(function(i) 286 { 287 var data = $(this).closest('.agenda').data('agenda'); 288 if (data) 289 { 290 data.setFirstColumn(firstCol, animate); 291 } 292 }); 293 }; 294 295 /** 296 * Scroll an agenda to previous column 297 */ 298 $.fn.scrollAgendaToPrevious = function() 299 { 300 return this.each(function(i) 301 { 302 var data = $(this).closest('.agenda').data('agenda'); 303 if (data) 304 { 305 data.scrollPrevious(); 306 } 307 }); 308 }; 309 310 /** 311 * Scroll an agenda to next column 312 */ 313 $.fn.scrollAgendaToNext = function() 314 { 315 return this.each(function(i) 316 { 317 var data = $(this).closest('.agenda').data('agenda'); 318 if (data) 319 { 320 data.scrollNext(); 321 } 322 }); 323 }; 324 325 /** 326 * Scroll agenda defaults 327 * @var object 328 */ 329 $.fn.scrollAgenda.defaults = { 330 /** 331 * Should the plugin automatically determine the number of visible columns? 332 * @var boolean 333 */ 334 auto: true, 335 336 /** 337 * Number of visible columns if auto is false 338 * @var int 339 */ 340 columns: 1, 341 342 /** 343 * Minimum columns width for auto detection 344 * @var int 345 */ 346 minWidth: 200, 347 348 /** 349 * Animate column movement 350 * @var boolean 351 */ 352 animate: true, 353 354 /** 355 * First visible column - starts at 0 (only used at startup) 356 * @var int 357 */ 358 first: 0, 359 360 /** 361 * Previous arrow title 362 * @var string 363 */ 364 prevTitle: 'Previous', 365 366 /** 367 * Next arrow title 368 * @var string 369 */ 370 nextTitle: 'Next', 371 372 /** 373 * Callback fired each time the number of visible columns change (including at startup) 374 * The function gets one parameter, the new number of visible columns 375 * @var function 376 */ 377 onSizeChange: null, 378 379 /** 380 * Callback fired each time the visible range changes 381 * The function gets 2 parameters: first and last visible columns' index (start at 0) 382 * @var function 383 */ 384 onRangeChange: null 385 }; 386 387 // Add template setup function 388 $.template.addSetupFunction(function(self, children) 389 { 390 // Auto-scrolling agendas 391 this.findIn(self, children, '.auto-scroll').scrollAgenda(); 392 393 return this; 394 }); 395 396})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.