Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/* global H5PAdminIntegration*/
2
var H5PUtils = H5PUtils || {};
3
 
4
(function ($) {
5
  /**
6
   * Generic function for creating a table including the headers
7
   *
8
   * @param {array} headers List of headers
9
   */
10
  H5PUtils.createTable = function (headers) {
11
    var $table = $('<table class="h5p-admin-table' + (H5PAdminIntegration.extraTableClasses !== undefined ? ' ' + H5PAdminIntegration.extraTableClasses : '') + '"></table>');
12
 
13
    if (headers) {
14
      var $thead = $('<thead></thead>');
15
      var $tr = $('<tr></tr>');
16
 
17
      $.each(headers, function (index, value) {
18
        if (!(value instanceof Object)) {
19
          value = {
20
            html: value
21
          };
22
        }
23
 
24
        $('<th/>', value).appendTo($tr);
25
      });
26
 
27
      $table.append($thead.append($tr));
28
    }
29
 
30
    return $table;
31
  };
32
 
33
  /**
34
   * Generic function for creating a table row
35
   *
36
   * @param {array} rows Value list. Object name is used as class name in <TD>
37
   */
38
  H5PUtils.createTableRow = function (rows) {
39
    var $tr = $('<tr></tr>');
40
 
41
    $.each(rows, function (index, value) {
42
      if (!(value instanceof Object)) {
43
        value = {
44
          html: value
45
        };
46
      }
47
 
48
      $('<td/>', value).appendTo($tr);
49
    });
50
 
51
    return $tr;
52
  };
53
 
54
  /**
55
   * Generic function for creating a field containing label and value
56
   *
57
   * @param {string} label The label displayed in front of the value
58
   * @param {string} value The value
59
   */
60
  H5PUtils.createLabeledField = function (label, value) {
61
    var $field = $('<div class="h5p-labeled-field"></div>');
62
 
63
    $field.append('<div class="h5p-label">' + label + '</div>');
64
    $field.append('<div class="h5p-value">' + value + '</div>');
65
 
66
    return $field;
67
  };
68
 
69
  /**
70
   * Replaces placeholder fields in translation strings
71
   *
72
   * @param {string} template The translation template string in the following format: "$name is a $sex"
73
   * @param {array} replacors An js object with key and values. Eg: {'$name': 'Frode', '$sex': 'male'}
74
   */
75
  H5PUtils.translateReplace = function (template, replacors) {
76
    $.each(replacors, function (key, value) {
77
      template = template.replace(new RegExp('\\'+key, 'g'), value);
78
    });
79
    return template;
80
  };
81
 
82
  /**
83
   * Get throbber with given text.
84
   *
85
   * @param {String} text
86
   * @returns {$}
87
   */
88
  H5PUtils.throbber = function (text) {
89
    return $('<div/>', {
90
      class: 'h5p-throbber',
91
      text: text
92
    });
93
  };
94
 
95
  /**
96
   * Makes it possbile to rebuild all content caches from admin UI.
97
   * @param {Object} notCached
98
   * @returns {$}
99
   */
100
  H5PUtils.getRebuildCache = function (notCached) {
101
    var $container = $('<div class="h5p-admin-rebuild-cache"><p class="message">' + notCached.message + '</p><p class="progress">' + notCached.progress + '</p></div>');
102
    var $button = $('<button>' + notCached.button + '</button>').appendTo($container).click(function () {
103
      var $spinner = $('<div/>', {class: 'h5p-spinner'}).replaceAll($button);
104
      var parts = ['|', '/', '-', '\\'];
105
      var current = 0;
106
      var spinning = setInterval(function () {
107
        $spinner.text(parts[current]);
108
        current++;
109
        if (current === parts.length) current = 0;
110
      }, 100);
111
 
112
      var $counter = $container.find('.progress');
113
      var build = function () {
114
        $.post(notCached.url, function (left) {
115
          if (left === '0') {
116
            clearInterval(spinning);
117
            $container.remove();
118
            location.reload();
119
          }
120
          else {
121
            var counter = $counter.text().split(' ');
122
            counter[0] = left;
123
            $counter.text(counter.join(' '));
124
            build();
125
          }
126
        });
127
      };
128
      build();
129
    });
130
 
131
    return $container;
132
  };
133
 
134
  /**
135
   * Generic table class with useful helpers.
136
   *
137
   * @class
138
   * @param {Object} classes
139
   *   Custom html classes to use on elements.
140
   *   e.g. {tableClass: 'fixed'}.
141
   */
142
  H5PUtils.Table = function (classes) {
143
    var numCols;
144
    var sortByCol;
145
    var $sortCol;
146
    var sortCol;
147
    var sortDir;
148
 
149
    // Create basic table
150
    var tableOptions = {};
151
    if (classes.table !== undefined) {
152
      tableOptions['class'] = classes.table;
153
    }
154
    var $table = $('<table/>', tableOptions);
155
    var $thead = $('<thead/>').appendTo($table);
156
    var $tfoot = $('<tfoot/>').appendTo($table);
157
    var $tbody = $('<tbody/>').appendTo($table);
158
 
159
    /**
160
     * Add columns to given table row.
161
     *
162
     * @private
163
     * @param {jQuery} $tr Table row
164
     * @param {(String|Object)} col Column properties
165
     * @param {Number} id Used to seperate the columns
166
     */
167
    var addCol = function ($tr, col, id) {
168
      var options = {
169
        on: {}
170
      };
171
 
172
      if (!(col instanceof Object)) {
173
        options.text = col;
174
      }
175
      else {
176
        if (col.text !== undefined) {
177
          options.text = col.text;
178
        }
179
        if (col.class !== undefined) {
180
          options.class = col.class;
181
        }
182
 
183
        if (sortByCol !== undefined && col.sortable === true) {
184
          // Make sortable
185
          options.role = 'button';
186
          options.tabIndex = 0;
187
 
188
          // This is the first sortable column, use as default sort
189
          if (sortCol === undefined) {
190
            sortCol = id;
191
            sortDir = 0;
192
          }
193
 
194
          // This is the sort column
195
          if (sortCol === id) {
196
            options['class'] = 'h5p-sort';
197
            if (sortDir === 1) {
198
              options['class'] += ' h5p-reverse';
199
            }
200
          }
201
 
202
          options.on.click = function () {
203
            sort($th, id);
204
          };
205
          options.on.keypress = function (event) {
206
            if ((event.charCode || event.keyCode) === 32) { // Space
207
              sort($th, id);
208
            }
209
          };
210
        }
211
      }
212
 
213
      // Append
214
      var $th = $('<th>', options).appendTo($tr);
215
      if (sortCol === id) {
216
        $sortCol = $th; // Default sort column
217
      }
218
    };
219
 
220
    /**
221
     * Updates the UI when a column header has been clicked.
222
     * Triggers sorting callback.
223
     *
224
     * @private
225
     * @param {jQuery} $th Table header
226
     * @param {Number} id Used to seperate the columns
227
     */
228
    var sort = function ($th, id) {
229
      if (id === sortCol) {
230
        // Change sorting direction
231
        if (sortDir === 0) {
232
          sortDir = 1;
233
          $th.addClass('h5p-reverse');
234
        }
235
        else {
236
          sortDir = 0;
237
          $th.removeClass('h5p-reverse');
238
        }
239
      }
240
      else {
241
        // Change sorting column
242
        $sortCol.removeClass('h5p-sort').removeClass('h5p-reverse');
243
        $sortCol = $th.addClass('h5p-sort');
244
        sortCol = id;
245
        sortDir = 0;
246
      }
247
 
248
      sortByCol({
249
        by: sortCol,
250
        dir: sortDir
251
      });
252
    };
253
 
254
    /**
255
     * Set table headers.
256
     *
257
     * @public
258
     * @param {Array} cols
259
     *   Table header data. Can be strings or objects with options like
260
     *   "text" and "sortable". E.g.
261
     *   [{text: 'Col 1', sortable: true}, 'Col 2', 'Col 3']
262
     * @param {Function} sort Callback which is runned when sorting changes
263
     * @param {Object} [order]
264
     */
265
    this.setHeaders = function (cols, sort, order) {
266
      numCols = cols.length;
267
      sortByCol = sort;
268
 
269
      if (order) {
270
        sortCol = order.by;
271
        sortDir = order.dir;
272
      }
273
 
274
      // Create new head
275
      var $newThead = $('<thead/>');
276
      var $tr = $('<tr/>').appendTo($newThead);
277
      for (var i = 0; i < cols.length; i++) {
278
        addCol($tr, cols[i], i);
279
      }
280
 
281
      // Update DOM
282
      $thead.replaceWith($newThead);
283
      $thead = $newThead;
284
    };
285
 
286
    /**
287
     * Set table rows.
288
     *
289
     * @public
290
     * @param {Array} rows Table rows with cols: [[1,'hello',3],[2,'asd',6]]
291
     */
292
    this.setRows = function (rows) {
293
      var $newTbody = $('<tbody/>');
294
 
295
      for (var i = 0; i < rows.length; i++) {
296
        var $tr = $('<tr/>').appendTo($newTbody);
297
 
298
        for (var j = 0; j < rows[i].length; j++) {
299
          $('<td>', {
300
            html: rows[i][j]
301
          }).appendTo($tr);
302
        }
303
      }
304
 
305
      $tbody.replaceWith($newTbody);
306
      $tbody = $newTbody;
307
 
308
      return $tbody;
309
    };
310
 
311
    /**
312
     * Set custom table body content. This can be a message or a throbber.
313
     * Will cover all table columns.
314
     *
315
     * @public
316
     * @param {jQuery} $content Custom content
317
     */
318
    this.setBody = function ($content) {
319
      var $newTbody = $('<tbody/>');
320
      var $tr = $('<tr/>').appendTo($newTbody);
321
      $('<td>', {
322
        colspan: numCols
323
      }).append($content).appendTo($tr);
324
      $tbody.replaceWith($newTbody);
325
      $tbody = $newTbody;
326
    };
327
 
328
    /**
329
     * Set custom table foot content. This can be a pagination widget.
330
     * Will cover all table columns.
331
     *
332
     * @public
333
     * @param {jQuery} $content Custom content
334
     */
335
    this.setFoot = function ($content) {
336
      var $newTfoot = $('<tfoot/>');
337
      var $tr = $('<tr/>').appendTo($newTfoot);
338
      $('<td>', {
339
        colspan: numCols
340
      }).append($content).appendTo($tr);
341
      $tfoot.replaceWith($newTfoot);
342
    };
343
 
344
 
345
    /**
346
     * Appends the table to the given container.
347
     *
348
     * @public
349
     * @param {jQuery} $container
350
     */
351
    this.appendTo = function ($container) {
352
      $table.appendTo($container);
353
    };
354
  };
355
 
356
  /**
357
   * Generic pagination class. Creates a useful pagination widget.
358
   *
359
   * @class
360
   * @param {Number} num Total number of items to pagiate.
361
   * @param {Number} limit Number of items to dispaly per page.
362
   * @param {Function} goneTo
363
   *   Callback which is fired when the user wants to go to another page.
364
   * @param {Object} l10n
365
   *   Localization / translations. e.g.
366
   *   {
367
   *     currentPage: 'Page $current of $total',
368
   *     nextPage: 'Next page',
369
   *     previousPage: 'Previous page'
370
   *   }
371
   */
372
  H5PUtils.Pagination = function (num, limit, goneTo, l10n) {
373
    var current = 0;
374
    var pages = Math.ceil(num / limit);
375
 
376
    // Create components
377
 
378
    // Previous button
379
    var $left = $('<button/>', {
380
      html: '&lt;',
381
      'class': 'button',
382
      title: l10n.previousPage
383
    }).click(function () {
384
      goTo(current - 1);
385
    });
386
 
387
    // Current page text
388
    var $text = $('<span/>').click(function () {
389
      $input.width($text.width()).show().val(current + 1).focus();
390
      $text.hide();
391
    });
392
 
393
    // Jump to page input
394
    var $input = $('<input/>', {
395
      type: 'number',
396
      min : 1,
397
      max: pages,
398
      on: {
399
        'blur': function () {
400
          gotInput();
401
        },
402
        'keyup': function (event) {
403
          if (event.keyCode === 13) {
404
            gotInput();
405
            return false;
406
          }
407
        }
408
      }
409
    }).hide();
410
 
411
    // Next button
412
    var $right = $('<button/>', {
413
      html: '&gt;',
414
      'class': 'button',
415
      title: l10n.nextPage
416
    }).click(function () {
417
      goTo(current + 1);
418
    });
419
 
420
    /**
421
     * Check what page the user has typed in and jump to it.
422
     *
423
     * @private
424
     */
425
    var gotInput = function () {
426
      var page = parseInt($input.hide().val());
427
      if (!isNaN(page)) {
428
        goTo(page - 1);
429
      }
430
      $text.show();
431
    };
432
 
433
    /**
434
     * Update UI elements.
435
     *
436
     * @private
437
     */
438
    var updateUI = function () {
439
      var next = current + 1;
440
 
441
      // Disable or enable buttons
442
      $left.attr('disabled', current === 0);
443
      $right.attr('disabled', next === pages);
444
 
445
      // Update counter
446
      $text.html(l10n.currentPage.replace('$current', next).replace('$total', pages));
447
    };
448
 
449
    /**
450
     * Try to go to the requested page.
451
     *
452
     * @private
453
     * @param {Number} page
454
     */
455
    var goTo = function (page) {
456
      if (page === current || page < 0 || page >= pages) {
457
        return; // Invalid page number
458
      }
459
      current = page;
460
 
461
      updateUI();
462
 
463
      // Fire callback
464
      goneTo(page * limit);
465
    };
466
 
467
    /**
468
     * Update number of items and limit.
469
     *
470
     * @public
471
     * @param {Number} newNum Total number of items to pagiate.
472
     * @param {Number} newLimit Number of items to dispaly per page.
473
     */
474
    this.update = function (newNum, newLimit) {
475
      if (newNum !== num || newLimit !== limit) {
476
        // Update num and limit
477
        num = newNum;
478
        limit = newLimit;
479
        pages = Math.ceil(num / limit);
480
        $input.attr('max', pages);
481
 
482
        if (current >= pages) {
483
          // Content is gone, move to last page.
484
          goTo(pages - 1);
485
          return;
486
        }
487
 
488
        updateUI();
489
      }
490
    };
491
 
492
    /**
493
     * Append the pagination widget to the given container.
494
     *
495
     * @public
496
     * @param {jQuery} $container
497
     */
498
    this.appendTo = function ($container) {
499
      $left.add($text).add($input).add($right).appendTo($container);
500
    };
501
 
502
    // Update UI
503
    updateUI();
504
  };
505
 
506
})(H5P.jQuery);