Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50659 views
1
// Copyright (c) IPython Development Team.
2
// Distributed under the terms of the Modified BSD License.
3
4
define([
5
"widgets/js/widget",
6
"base/js/utils",
7
"jquery",
8
"underscore",
9
"bootstrap",
10
], function(widget, utils, $, _){
11
12
var DropdownView = widget.DOMWidgetView.extend({
13
render : function(){
14
/**
15
* Called when view is rendered.
16
*/
17
this.$el
18
.addClass('widget-hbox widget-dropdown');
19
this.$label = $('<div />')
20
.appendTo(this.$el)
21
.addClass('widget-label')
22
.hide();
23
this.$buttongroup = $('<div />')
24
.addClass('widget_item')
25
.addClass('btn-group')
26
.appendTo(this.$el);
27
this.$droplabel = $('<button />')
28
.addClass('btn btn-default')
29
.addClass('widget-combo-btn')
30
.html("&nbsp;")
31
.appendTo(this.$buttongroup);
32
this.$dropbutton = $('<button />')
33
.addClass('btn btn-default')
34
.addClass('dropdown-toggle')
35
.addClass('widget-combo-carrot-btn')
36
.attr('data-toggle', 'dropdown')
37
.append($('<span />').addClass("caret"))
38
.appendTo(this.$buttongroup);
39
this.$droplist = $('<ul />')
40
.addClass('dropdown-menu')
41
.appendTo(this.$buttongroup);
42
43
this.model.on('change:button_style', function(model, value) {
44
this.update_button_style();
45
}, this);
46
this.update_button_style('');
47
48
// Set defaults.
49
this.update();
50
},
51
52
update : function(options){
53
/**
54
* Update the contents of this view
55
*
56
* Called when the model is changed. The model may have been
57
* changed by another view or by a state update from the back-end.
58
*/
59
60
if (options === undefined || options.updated_view != this) {
61
var selected_item_text = this.model.get('selected_label');
62
if (selected_item_text.trim().length === 0) {
63
this.$droplabel.html("&nbsp;");
64
} else {
65
this.$droplabel.text(selected_item_text);
66
}
67
68
var items = this.model.get('_options_labels');
69
var $replace_droplist = $('<ul />')
70
.addClass('dropdown-menu');
71
// Copy the style
72
$replace_droplist.attr('style', this.$droplist.attr('style'));
73
var that = this;
74
_.each(items, function(item, i) {
75
var item_button = $('<a href="#"/>')
76
.text(item)
77
.on('click', $.proxy(that.handle_click, that));
78
$replace_droplist.append($('<li />').append(item_button));
79
});
80
81
this.$droplist.replaceWith($replace_droplist);
82
this.$droplist.remove();
83
this.$droplist = $replace_droplist;
84
85
if (this.model.get('disabled')) {
86
this.$buttongroup.attr('disabled','disabled');
87
this.$droplabel.attr('disabled','disabled');
88
this.$dropbutton.attr('disabled','disabled');
89
this.$droplist.attr('disabled','disabled');
90
} else {
91
this.$buttongroup.removeAttr('disabled');
92
this.$droplabel.removeAttr('disabled');
93
this.$dropbutton.removeAttr('disabled');
94
this.$droplist.removeAttr('disabled');
95
}
96
97
var description = this.model.get('description');
98
if (description.length === 0) {
99
this.$label.hide();
100
} else {
101
this.typeset(this.$label, description);
102
this.$label.show();
103
}
104
}
105
return DropdownView.__super__.update.apply(this);
106
},
107
108
update_button_style: function(previous_trait_value) {
109
var class_map = {
110
primary: ['btn-primary'],
111
success: ['btn-success'],
112
info: ['btn-info'],
113
warning: ['btn-warning'],
114
danger: ['btn-danger']
115
};
116
this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$droplabel);
117
this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$dropbutton);
118
},
119
120
update_attr: function(name, value) {
121
/**
122
* Set a css attr of the widget view.
123
*/
124
if (name.substring(0, 6) == 'border' || name == 'background' || name == 'color') {
125
this.$droplabel.css(name, value);
126
this.$dropbutton.css(name, value);
127
this.$droplist.css(name, value);
128
} else if (name == 'width') {
129
this.$droplist.css(name, value);
130
this.$droplabel.css(name, value);
131
} else if (name == 'padding') {
132
this.$droplist.css(name, value);
133
this.$buttongroup.css(name, value);
134
} else if (name == 'margin') {
135
this.$buttongroup.css(name, value);
136
} else if (name == 'height') {
137
this.$droplabel.css(name, value);
138
this.$dropbutton.css(name, value);
139
} else if (name == 'padding' || name == 'margin') {
140
this.$el.css(name, value);
141
} else {
142
this.$droplist.css(name, value);
143
this.$droplabel.css(name, value);
144
}
145
},
146
147
handle_click: function (e) {
148
/**
149
* Handle when a value is clicked.
150
*
151
* Calling model.set will trigger all of the other views of the
152
* model to update.
153
*/
154
this.model.set('selected_label', $(e.target).text(), {updated_view: this});
155
this.touch();
156
157
// Manually hide the droplist.
158
e.stopPropagation();
159
e.preventDefault();
160
this.$buttongroup.removeClass('open');
161
},
162
163
});
164
165
166
var RadioButtonsView = widget.DOMWidgetView.extend({
167
render : function(){
168
/**
169
* Called when view is rendered.
170
*/
171
this.$el
172
.addClass('widget-hbox widget-radio');
173
this.$label = $('<div />')
174
.appendTo(this.$el)
175
.addClass('widget-label')
176
.hide();
177
this.$container = $('<div />')
178
.appendTo(this.$el)
179
.addClass('widget-radio-box');
180
this.update();
181
},
182
183
update : function(options){
184
/**
185
* Update the contents of this view
186
*
187
* Called when the model is changed. The model may have been
188
* changed by another view or by a state update from the back-end.
189
*/
190
if (options === undefined || options.updated_view != this) {
191
// Add missing items to the DOM.
192
var items = this.model.get('_options_labels');
193
var disabled = this.model.get('disabled');
194
var that = this;
195
_.each(items, function(item, index) {
196
var item_query = ' :input[data-value="' + encodeURIComponent(item) + '"]';
197
if (that.$el.find(item_query).length === 0) {
198
var $label = $('<label />')
199
.addClass('radio')
200
.text(item)
201
.appendTo(that.$container);
202
203
$('<input />')
204
.attr('type', 'radio')
205
.addClass(that.model)
206
.val(item)
207
.attr('data-value', encodeURIComponent(item))
208
.prependTo($label)
209
.on('click', $.proxy(that.handle_click, that));
210
}
211
212
var $item_element = that.$container.find(item_query);
213
if (that.model.get('selected_label') == item) {
214
$item_element.prop('checked', true);
215
} else {
216
$item_element.prop('checked', false);
217
}
218
$item_element.prop('disabled', disabled);
219
});
220
221
// Remove items that no longer exist.
222
this.$container.find('input').each(function(i, obj) {
223
var value = $(obj).val();
224
var found = false;
225
_.each(items, function(item, index) {
226
if (item == value) {
227
found = true;
228
return false;
229
}
230
});
231
232
if (!found) {
233
$(obj).parent().remove();
234
}
235
});
236
237
var description = this.model.get('description');
238
if (description.length === 0) {
239
this.$label.hide();
240
} else {
241
this.$label.text(description);
242
this.typeset(this.$label, description);
243
this.$label.show();
244
}
245
}
246
return RadioButtonsView.__super__.update.apply(this);
247
},
248
249
update_attr: function(name, value) {
250
/**
251
* Set a css attr of the widget view.
252
*/
253
if (name == 'padding' || name == 'margin') {
254
this.$el.css(name, value);
255
} else {
256
this.$container.css(name, value);
257
}
258
},
259
260
handle_click: function (e) {
261
/**
262
* Handle when a value is clicked.
263
*
264
* Calling model.set will trigger all of the other views of the
265
* model to update.
266
*/
267
this.model.set('selected_label', $(e.target).val(), {updated_view: this});
268
this.touch();
269
},
270
});
271
272
273
var ToggleButtonsView = widget.DOMWidgetView.extend({
274
initialize: function() {
275
this._css_state = {};
276
ToggleButtonsView.__super__.initialize.apply(this, arguments);
277
},
278
279
render: function() {
280
/**
281
* Called when view is rendered.
282
*/
283
this.$el
284
.addClass('widget-hbox widget-toggle-buttons');
285
this.$label = $('<div />')
286
.appendTo(this.$el)
287
.addClass('widget-label')
288
.hide();
289
this.$buttongroup = $('<div />')
290
.addClass('btn-group')
291
.appendTo(this.$el);
292
293
this.model.on('change:button_style', function(model, value) {
294
this.update_button_style();
295
}, this);
296
this.update_button_style('');
297
this.update();
298
},
299
300
update : function(options){
301
/**
302
* Update the contents of this view
303
*
304
* Called when the model is changed. The model may have been
305
* changed by another view or by a state update from the back-end.
306
*/
307
if (options === undefined || options.updated_view != this) {
308
// Add missing items to the DOM.
309
var items = this.model.get('_options_labels');
310
var icons = this.model.get('icons');
311
var previous_icons = this.model.previous('icons') || [];
312
var disabled = this.model.get('disabled');
313
var that = this;
314
var item_html;
315
_.each(items, function(item, index) {
316
if (item.trim().length === 0 && (!icons[index] ||
317
icons[index].trim().length === 0)) {
318
item_html = "&nbsp;";
319
} else {
320
item_html = utils.escape_html(item);
321
}
322
var item_query = '[data-value="' + encodeURIComponent(item) + '"]';
323
var $item_element = that.$buttongroup.find(item_query);
324
var $icon_element = $item_element.find('.fa');
325
if (!$item_element.length) {
326
$item_element = $('<button/>')
327
.attr('type', 'button')
328
.addClass('btn btn-default')
329
.html(item_html)
330
.appendTo(that.$buttongroup)
331
.attr('data-value', encodeURIComponent(item))
332
.attr('data-toggle', 'tooltip')
333
.attr('value', item)
334
.on('click', $.proxy(that.handle_click, that));
335
that.update_style_traits($item_element);
336
$icon_element = $('<i class="fa"></i>').prependTo($item_element);
337
}
338
if (that.model.get('selected_label') == item) {
339
$item_element.addClass('active');
340
} else {
341
$item_element.removeClass('active');
342
}
343
$item_element.prop('disabled', disabled);
344
$item_element.attr('title', that.model.get('tooltips')[index]);
345
$icon_element
346
.removeClass(previous_icons[index])
347
.addClass(icons[index]);
348
});
349
350
// Remove items that no longer exist.
351
this.$buttongroup.find('button').each(function(i, obj) {
352
var value = $(obj).attr('value');
353
var found = false;
354
_.each(items, function(item, index) {
355
if (item == value) {
356
found = true;
357
return false;
358
}
359
});
360
361
if (!found) {
362
$(obj).remove();
363
}
364
});
365
366
var description = this.model.get('description');
367
if (description.length === 0) {
368
this.$label.hide();
369
} else {
370
this.$label.text();
371
this.typeset(this.$label, description);
372
this.$label.show();
373
}
374
}
375
return ToggleButtonsView.__super__.update.apply(this);
376
},
377
378
update_attr: function(name, value) {
379
/**
380
* Set a css attr of the widget view.
381
*/
382
if (name == 'padding' || name == 'margin') {
383
this.$el.css(name, value);
384
} else {
385
this._css_state[name] = value;
386
this.update_style_traits();
387
}
388
},
389
390
update_style_traits: function(button) {
391
for (var name in this._css_state) {
392
if (this._css_state.hasOwnProperty(name)) {
393
if (name == 'margin') {
394
this.$buttongroup.css(name, this._css_state[name]);
395
} else if (name != 'width') {
396
if (button) {
397
button.css(name, this._css_state[name]);
398
} else {
399
this.$buttongroup.find('button').css(name, this._css_state[name]);
400
}
401
}
402
}
403
}
404
},
405
406
update_button_style: function(previous_trait_value) {
407
var class_map = {
408
primary: ['btn-primary'],
409
success: ['btn-success'],
410
info: ['btn-info'],
411
warning: ['btn-warning'],
412
danger: ['btn-danger']
413
};
414
this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$buttongroup.find('button'));
415
},
416
417
handle_click: function (e) {
418
/**
419
* Handle when a value is clicked.
420
*
421
* Calling model.set will trigger all of the other views of the
422
* model to update.
423
*/
424
this.model.set('selected_label', $(e.target).attr('value'), {updated_view: this});
425
this.touch();
426
},
427
});
428
429
430
var SelectView = widget.DOMWidgetView.extend({
431
render : function(){
432
/**
433
* Called when view is rendered.
434
*/
435
this.$el
436
.addClass('widget-hbox widget-select');
437
this.$label = $('<div />')
438
.appendTo(this.$el)
439
.addClass('widget-label')
440
.hide();
441
this.$listbox = $('<select />')
442
.addClass('widget-listbox form-control')
443
.attr('size', 6)
444
.appendTo(this.$el)
445
.on('change', $.proxy(this.handle_change, this));
446
this.update();
447
},
448
449
update : function(options){
450
/**
451
* Update the contents of this view
452
*
453
* Called when the model is changed. The model may have been
454
* changed by another view or by a state update from the back-end.
455
*/
456
if (options === undefined || options.updated_view != this) {
457
// Add missing items to the DOM.
458
var items = this.model.get('_options_labels');
459
var that = this;
460
_.each(items, function(item, index) {
461
var item_query = 'option[data-value="' + encodeURIComponent(item) + '"]';
462
if (that.$listbox.find(item_query).length === 0) {
463
$('<option />')
464
.text(item)
465
.attr('data-value', encodeURIComponent(item))
466
.attr('selected_label', item)
467
.on("click", $.proxy(that.handle_click, that))
468
.appendTo(that.$listbox);
469
}
470
});
471
472
// Select the correct element
473
this.$listbox.val(this.model.get('selected_label'));
474
475
// Disable listbox if needed
476
var disabled = this.model.get('disabled');
477
this.$listbox.prop('disabled', disabled);
478
479
// Remove items that no longer exist.
480
this.$listbox.find('option').each(function(i, obj) {
481
var value = $(obj).text();
482
var found = false;
483
_.each(items, function(item, index) {
484
if (item == value) {
485
found = true;
486
return false;
487
}
488
});
489
490
if (!found) {
491
$(obj).remove();
492
}
493
});
494
495
var description = this.model.get('description');
496
if (description.length === 0) {
497
this.$label.hide();
498
} else {
499
this.typeset(this.$label, description);
500
this.$label.show();
501
}
502
}
503
return SelectView.__super__.update.apply(this);
504
},
505
506
update_attr: function(name, value) {
507
/**
508
* Set a css attr of the widget view.
509
*/
510
if (name == 'padding' || name == 'margin') {
511
this.$el.css(name, value);
512
} else {
513
this.$listbox.css(name, value);
514
}
515
},
516
517
handle_click: function (e) {
518
/**
519
* Handle when a new value is clicked.
520
*/
521
this.$listbox.val($(e.target).val()).change();
522
},
523
524
handle_change: function (e) {
525
/**
526
* Handle when a new value is selected.
527
*
528
* Calling model.set will trigger all of the other views of the
529
* model to update.
530
*/
531
this.model.set('selected_label', this.$listbox.val(), {updated_view: this});
532
this.touch();
533
},
534
});
535
536
537
var SelectMultipleView = SelectView.extend({
538
render: function(){
539
/**
540
* Called when view is rendered.
541
*/
542
SelectMultipleView.__super__.render.apply(this);
543
this.$el.removeClass('widget-select')
544
.addClass('widget-select-multiple');
545
this.$listbox.attr('multiple', true)
546
.on('change', $.proxy(this.handle_change, this));
547
return this;
548
},
549
550
update: function(){
551
/**
552
* Update the contents of this view
553
*
554
* Called when the model is changed. The model may have been
555
* changed by another view or by a state update from the back-end.
556
*/
557
SelectMultipleView.__super__.update.apply(this, arguments);
558
this.$listbox.val(this.model.get('selected_labels'));
559
},
560
561
handle_click: function(){
562
/**
563
* Overload click from select
564
*
565
* Apparently it's needed from there for testing purposes,
566
* but breaks behavior of this.
567
*/
568
},
569
570
handle_change: function (e) {
571
/**
572
* Handle when a new value is selected.
573
*
574
* Calling model.set will trigger all of the other views of the
575
* model to update.
576
*/
577
this.model.set('selected_labels',
578
(this.$listbox.val() || []).slice(),
579
{updated_view: this});
580
this.touch();
581
},
582
});
583
584
585
return {
586
'DropdownView': DropdownView,
587
'RadioButtonsView': RadioButtonsView,
588
'ToggleButtonsView': ToggleButtonsView,
589
'SelectView': SelectView,
590
'SelectMultipleView': SelectMultipleView,
591
};
592
});
593
594