volt-bootbox 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 170f96871975cea098d1f5c7c7b8230d0b56c917
4
+ data.tar.gz: a4f8aec87db3e44eca1c2b0cdd5a106125d823b7
5
+ SHA512:
6
+ metadata.gz: fc70eec8bfa555b11856c20fb5e0c7f4e6725ea60879af733a35c71648f82fcbb8d680e7d029ef121aeac2f0022207ce327dd55fd7f9c99c1d3f47550c72c24c
7
+ data.tar.gz: 2680898535c2b0b0a477347c27a48efdc42dea5e0562677e7ec443f19b8f222c0d3e11790d8c6999047e675553f5b48b40277932fa4b1f54a762eaed857ef8c3
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ # Change Log
2
+
3
+ ## 0.1.5
4
+
5
+ - README.md edits
6
+
7
+ ## 0.1.4
8
+
9
+ - assets/config/dependencies: https link to code.highcharts.com/highcharts.js, etc
10
+
11
+ ## 0.1.3
12
+
13
+ - added global animate option
14
+ - improvements to reactivity logic
15
+
16
+ ## 0.1.2
17
+
18
+ - various tweaks
19
+
20
+ ## 0.1.1
21
+
22
+ - now uses opal-highcharts gem
23
+ - first steps towards reactivitiy
24
+ - a chart is reactive if options are provided as a Volt::Model
25
+ - a chart is non-reactive if options are provided as a Hash
26
+
27
+ ### opal-highcharts
28
+ a gem which wraps most Highcharts and Highstock functionality in a client-side Ruby API.
29
+ - https://github.com/balmoral/opal-highcharts
30
+ - https://rubygems.org/gems/opal-highcharts
31
+
32
+
33
+
34
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in volt-highcharts.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Colin Gunn
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # Volt::Bootbox
2
+
3
+ A Volt component wrapping the Bootbox javascript library (via opal-bootbox).
4
+
5
+ Bootbox.js is a small open source (MIT) JavaScript library which implements dialog (alert, prompt, confirm) boxes using Bootstrap modals.
6
+
7
+ To find out more about Bootbox, go to http://bootboxjs.com.
8
+
9
+ To find out more about Opal, go to http://opalrb.org
10
+
11
+ To find out more about Volt, go to http://http://voltframework.com
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'volt-bootbox'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install volt-highcharts
26
+
27
+ ## Usage
28
+
29
+ First include the gem in the project's Gemfile:
30
+
31
+ ```gem 'volt-bootbox'```
32
+
33
+ Next add volt-bootbox to the dependencies.rb file:
34
+
35
+ ```component 'bootbox'```
36
+
37
+ ### Examples
38
+
39
+ ```
40
+ $bootbox.alert('Hello world!') do
41
+ puts 'hello world acknowledged'
42
+ end
43
+
44
+ $bootbox.alert(title: 'Alert dialog', message: 'Hello world!') do
45
+ puts 'hello world acknowledged'
46
+ end
47
+
48
+ $bootbox.confirm('Are you sure?') do |result|
49
+ puts "user is #{result ? 'sure' : 'unsure'}"
50
+ end
51
+
52
+ $bootbox.confirm(title: 'Confirmation dialog', message: Are you sure?') do |result|
53
+ puts "user is #{result ? 'sure' : 'unsure'}"
54
+ end
55
+
56
+ $bootbox.prompt('What is your name?') do |result|
57
+ if result
58
+ puts "user's name is '#{result}'"
59
+ else
60
+ puts "prompt dismissed"
61
+ end
62
+ end
63
+
64
+ $bootbox.prompt(title: 'Prompt dialog', message: 'What is your name?', value: 'default name') do |result|
65
+ if result
66
+ puts "user's name is '#{result}'"
67
+ else
68
+ puts "prompt dismissed"
69
+ end
70
+ end
71
+
72
+ ```
73
+
74
+ `$bootbox` is a global variable. `Volt::Bootbox` may be substituted.
75
+
76
+ Strings (text) provided as arguments to bootbox methods may be HTML format.
77
+
78
+ ## Contributing
79
+
80
+ Contributions, comments and suggestions are welcome.
81
+
82
+ 1. Fork it ( http://github.com/balmoral/volt-highcharts/fork )
83
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
84
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
85
+ 4. Push to the branch (`git push origin my-new-feature`)
86
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,985 @@
1
+ /**
2
+ * bootbox.js [v4.4.0]
3
+ *
4
+ * http://bootboxjs.com/license.txt
5
+ */
6
+
7
+ // @see https://github.com/makeusabrew/bootbox/issues/180
8
+ // @see https://github.com/makeusabrew/bootbox/issues/186
9
+ (function (root, factory) {
10
+
11
+ "use strict";
12
+ if (typeof define === "function" && define.amd) {
13
+ // AMD. Register as an anonymous module.
14
+ define(["jquery"], factory);
15
+ } else if (typeof exports === "object") {
16
+ // Node. Does not work with strict CommonJS, but
17
+ // only CommonJS-like environments that support module.exports,
18
+ // like Node.
19
+ module.exports = factory(require("jquery"));
20
+ } else {
21
+ // Browser globals (root is window)
22
+ root.bootbox = factory(root.jQuery);
23
+ }
24
+
25
+ }(this, function init($, undefined) {
26
+
27
+ "use strict";
28
+
29
+ // the base DOM structure needed to create a modal
30
+ var templates = {
31
+ dialog:
32
+ "<div class='bootbox modal' tabindex='-1' role='dialog'>" +
33
+ "<div class='modal-dialog'>" +
34
+ "<div class='modal-content'>" +
35
+ "<div class='modal-body'><div class='bootbox-body'></div></div>" +
36
+ "</div>" +
37
+ "</div>" +
38
+ "</div>",
39
+ header:
40
+ "<div class='modal-header'>" +
41
+ "<h4 class='modal-title'></h4>" +
42
+ "</div>",
43
+ footer:
44
+ "<div class='modal-footer'></div>",
45
+ closeButton:
46
+ "<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>&times;</button>",
47
+ form:
48
+ "<form class='bootbox-form'></form>",
49
+ inputs: {
50
+ text:
51
+ "<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",
52
+ textarea:
53
+ "<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",
54
+ email:
55
+ "<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",
56
+ select:
57
+ "<select class='bootbox-input bootbox-input-select form-control'></select>",
58
+ checkbox:
59
+ "<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",
60
+ date:
61
+ "<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",
62
+ time:
63
+ "<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",
64
+ number:
65
+ "<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",
66
+ password:
67
+ "<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"
68
+ }
69
+ };
70
+
71
+ var defaults = {
72
+ // default language
73
+ locale: "en",
74
+ // show backdrop or not. Default to static so user has to interact with dialog
75
+ backdrop: "static",
76
+ // animate the modal in/out
77
+ animate: true,
78
+ // additional class string applied to the top level dialog
79
+ className: null,
80
+ // whether or not to include a close button
81
+ closeButton: true,
82
+ // show the dialog immediately by default
83
+ show: true,
84
+ // dialog container
85
+ container: "body"
86
+ };
87
+
88
+ // our public object; augmented after our private API
89
+ var exports = {};
90
+
91
+ /**
92
+ * @private
93
+ */
94
+ function _t(key) {
95
+ var locale = locales[defaults.locale];
96
+ return locale ? locale[key] : locales.en[key];
97
+ }
98
+
99
+ function processCallback(e, dialog, callback) {
100
+ e.stopPropagation();
101
+ e.preventDefault();
102
+
103
+ // by default we assume a callback will get rid of the dialog,
104
+ // although it is given the opportunity to override this
105
+
106
+ // so, if the callback can be invoked and it *explicitly returns false*
107
+ // then we'll set a flag to keep the dialog active...
108
+ var preserveDialog = $.isFunction(callback) && callback.call(dialog, e) === false;
109
+
110
+ // ... otherwise we'll bin it
111
+ if (!preserveDialog) {
112
+ dialog.modal("hide");
113
+ }
114
+ }
115
+
116
+ function getKeyLength(obj) {
117
+ // @TODO defer to Object.keys(x).length if available?
118
+ var k, t = 0;
119
+ for (k in obj) {
120
+ t ++;
121
+ }
122
+ return t;
123
+ }
124
+
125
+ function each(collection, iterator) {
126
+ var index = 0;
127
+ $.each(collection, function(key, value) {
128
+ iterator(key, value, index++);
129
+ });
130
+ }
131
+
132
+ function sanitize(options) {
133
+ var buttons;
134
+ var total;
135
+
136
+ if (typeof options !== "object") {
137
+ throw new Error("Please supply an object of options");
138
+ }
139
+
140
+ if (!options.message) {
141
+ throw new Error("Please specify a message");
142
+ }
143
+
144
+ // make sure any supplied options take precedence over defaults
145
+ options = $.extend({}, defaults, options);
146
+
147
+ if (!options.buttons) {
148
+ options.buttons = {};
149
+ }
150
+
151
+ buttons = options.buttons;
152
+
153
+ total = getKeyLength(buttons);
154
+
155
+ each(buttons, function(key, button, index) {
156
+
157
+ if ($.isFunction(button)) {
158
+ // short form, assume value is our callback. Since button
159
+ // isn't an object it isn't a reference either so re-assign it
160
+ button = buttons[key] = {
161
+ callback: button
162
+ };
163
+ }
164
+
165
+ // before any further checks make sure by now button is the correct type
166
+ if ($.type(button) !== "object") {
167
+ throw new Error("button with key " + key + " must be an object");
168
+ }
169
+
170
+ if (!button.label) {
171
+ // the lack of an explicit label means we'll assume the key is good enough
172
+ button.label = key;
173
+ }
174
+
175
+ if (!button.className) {
176
+ if (total <= 2 && index === total-1) {
177
+ // always add a primary to the main option in a two-button dialog
178
+ button.className = "btn-primary";
179
+ } else {
180
+ button.className = "btn-default";
181
+ }
182
+ }
183
+ });
184
+
185
+ return options;
186
+ }
187
+
188
+ /**
189
+ * map a flexible set of arguments into a single returned object
190
+ * if args.length is already one just return it, otherwise
191
+ * use the properties argument to map the unnamed args to
192
+ * object properties
193
+ * so in the latter case:
194
+ * mapArguments(["foo", $.noop], ["message", "callback"])
195
+ * -> { message: "foo", callback: $.noop }
196
+ */
197
+ function mapArguments(args, properties) {
198
+ var argn = args.length;
199
+ var options = {};
200
+
201
+ if (argn < 1 || argn > 2) {
202
+ throw new Error("Invalid argument length");
203
+ }
204
+
205
+ if (argn === 2 || typeof args[0] === "string") {
206
+ options[properties[0]] = args[0];
207
+ options[properties[1]] = args[1];
208
+ } else {
209
+ options = args[0];
210
+ }
211
+
212
+ return options;
213
+ }
214
+
215
+ /**
216
+ * merge a set of default dialog options with user supplied arguments
217
+ */
218
+ function mergeArguments(defaults, args, properties) {
219
+ return $.extend(
220
+ // deep merge
221
+ true,
222
+ // ensure the target is an empty, unreferenced object
223
+ {},
224
+ // the base options object for this type of dialog (often just buttons)
225
+ defaults,
226
+ // args could be an object or array; if it's an array properties will
227
+ // map it to a proper options object
228
+ mapArguments(
229
+ args,
230
+ properties
231
+ )
232
+ );
233
+ }
234
+
235
+ /**
236
+ * this entry-level method makes heavy use of composition to take a simple
237
+ * range of inputs and return valid options suitable for passing to bootbox.dialog
238
+ */
239
+ function mergeDialogOptions(className, labels, properties, args) {
240
+ // build up a base set of dialog properties
241
+ var baseOptions = {
242
+ className: "bootbox-" + className,
243
+ buttons: createLabels.apply(null, labels)
244
+ };
245
+
246
+ // ensure the buttons properties generated, *after* merging
247
+ // with user args are still valid against the supplied labels
248
+ return validateButtons(
249
+ // merge the generated base properties with user supplied arguments
250
+ mergeArguments(
251
+ baseOptions,
252
+ args,
253
+ // if args.length > 1, properties specify how each arg maps to an object key
254
+ properties
255
+ ),
256
+ labels
257
+ );
258
+ }
259
+
260
+ /**
261
+ * from a given list of arguments return a suitable object of button labels
262
+ * all this does is normalise the given labels and translate them where possible
263
+ * e.g. "ok", "confirm" -> { ok: "OK, cancel: "Annuleren" }
264
+ */
265
+ function createLabels() {
266
+ var buttons = {};
267
+
268
+ for (var i = 0, j = arguments.length; i < j; i++) {
269
+ var argument = arguments[i];
270
+ var key = argument.toLowerCase();
271
+ var value = argument.toUpperCase();
272
+
273
+ buttons[key] = {
274
+ label: _t(value)
275
+ };
276
+ }
277
+
278
+ return buttons;
279
+ }
280
+
281
+ function validateButtons(options, buttons) {
282
+ var allowedButtons = {};
283
+ each(buttons, function(key, value) {
284
+ allowedButtons[value] = true;
285
+ });
286
+
287
+ each(options.buttons, function(key) {
288
+ if (allowedButtons[key] === undefined) {
289
+ throw new Error("button key " + key + " is not allowed (options are " + buttons.join("\n") + ")");
290
+ }
291
+ });
292
+
293
+ return options;
294
+ }
295
+
296
+ exports.alert = function() {
297
+ var options;
298
+
299
+ options = mergeDialogOptions("alert", ["ok"], ["message", "callback"], arguments);
300
+
301
+ if (options.callback && !$.isFunction(options.callback)) {
302
+ throw new Error("alert requires callback property to be a function when provided");
303
+ }
304
+
305
+ /**
306
+ * overrides
307
+ */
308
+ options.buttons.ok.callback = options.onEscape = function() {
309
+ if ($.isFunction(options.callback)) {
310
+ return options.callback.call(this);
311
+ }
312
+ return true;
313
+ };
314
+
315
+ return exports.dialog(options);
316
+ };
317
+
318
+ exports.confirm = function() {
319
+ var options;
320
+
321
+ options = mergeDialogOptions("confirm", ["cancel", "confirm"], ["message", "callback"], arguments);
322
+
323
+ /**
324
+ * overrides; undo anything the user tried to set they shouldn't have
325
+ */
326
+ options.buttons.cancel.callback = options.onEscape = function() {
327
+ return options.callback.call(this, false);
328
+ };
329
+
330
+ options.buttons.confirm.callback = function() {
331
+ return options.callback.call(this, true);
332
+ };
333
+
334
+ // confirm specific validation
335
+ if (!$.isFunction(options.callback)) {
336
+ throw new Error("confirm requires a callback");
337
+ }
338
+
339
+ return exports.dialog(options);
340
+ };
341
+
342
+ exports.prompt = function() {
343
+ var options;
344
+ var defaults;
345
+ var dialog;
346
+ var form;
347
+ var input;
348
+ var shouldShow;
349
+ var inputOptions;
350
+
351
+ // we have to create our form first otherwise
352
+ // its value is undefined when gearing up our options
353
+ // @TODO this could be solved by allowing message to
354
+ // be a function instead...
355
+ form = $(templates.form);
356
+
357
+ // prompt defaults are more complex than others in that
358
+ // users can override more defaults
359
+ // @TODO I don't like that prompt has to do a lot of heavy
360
+ // lifting which mergeDialogOptions can *almost* support already
361
+ // just because of 'value' and 'inputType' - can we refactor?
362
+ defaults = {
363
+ className: "bootbox-prompt",
364
+ buttons: createLabels("cancel", "confirm"),
365
+ value: "",
366
+ inputType: "text"
367
+ };
368
+
369
+ options = validateButtons(
370
+ mergeArguments(defaults, arguments, ["title", "callback"]),
371
+ ["cancel", "confirm"]
372
+ );
373
+
374
+ // capture the user's show value; we always set this to false before
375
+ // spawning the dialog to give us a chance to attach some handlers to
376
+ // it, but we need to make sure we respect a preference not to show it
377
+ shouldShow = (options.show === undefined) ? true : options.show;
378
+
379
+ /**
380
+ * overrides; undo anything the user tried to set they shouldn't have
381
+ */
382
+ options.message = form;
383
+
384
+ options.buttons.cancel.callback = options.onEscape = function() {
385
+ return options.callback.call(this, null);
386
+ };
387
+
388
+ options.buttons.confirm.callback = function() {
389
+ var value;
390
+
391
+ switch (options.inputType) {
392
+ case "text":
393
+ case "textarea":
394
+ case "email":
395
+ case "select":
396
+ case "date":
397
+ case "time":
398
+ case "number":
399
+ case "password":
400
+ value = input.val();
401
+ break;
402
+
403
+ case "checkbox":
404
+ var checkedItems = input.find("input:checked");
405
+
406
+ // we assume that checkboxes are always multiple,
407
+ // hence we default to an empty array
408
+ value = [];
409
+
410
+ each(checkedItems, function(_, item) {
411
+ value.push($(item).val());
412
+ });
413
+ break;
414
+ }
415
+
416
+ return options.callback.call(this, value);
417
+ };
418
+
419
+ options.show = false;
420
+
421
+ // prompt specific validation
422
+ if (!options.title) {
423
+ throw new Error("prompt requires a title");
424
+ }
425
+
426
+ if (!$.isFunction(options.callback)) {
427
+ throw new Error("prompt requires a callback");
428
+ }
429
+
430
+ if (!templates.inputs[options.inputType]) {
431
+ throw new Error("invalid prompt type");
432
+ }
433
+
434
+ // create the input based on the supplied type
435
+ input = $(templates.inputs[options.inputType]);
436
+
437
+ switch (options.inputType) {
438
+ case "text":
439
+ case "textarea":
440
+ case "email":
441
+ case "date":
442
+ case "time":
443
+ case "number":
444
+ case "password":
445
+ input.val(options.value);
446
+ break;
447
+
448
+ case "select":
449
+ var groups = {};
450
+ inputOptions = options.inputOptions || [];
451
+
452
+ if (!$.isArray(inputOptions)) {
453
+ throw new Error("Please pass an array of input options");
454
+ }
455
+
456
+ if (!inputOptions.length) {
457
+ throw new Error("prompt with select requires options");
458
+ }
459
+
460
+ each(inputOptions, function(_, option) {
461
+
462
+ // assume the element to attach to is the input...
463
+ var elem = input;
464
+
465
+ if (option.value === undefined || option.text === undefined) {
466
+ throw new Error("given options in wrong format");
467
+ }
468
+
469
+ // ... but override that element if this option sits in a group
470
+
471
+ if (option.group) {
472
+ // initialise group if necessary
473
+ if (!groups[option.group]) {
474
+ groups[option.group] = $("<optgroup/>").attr("label", option.group);
475
+ }
476
+
477
+ elem = groups[option.group];
478
+ }
479
+
480
+ elem.append("<option value='" + option.value + "'>" + option.text + "</option>");
481
+ });
482
+
483
+ each(groups, function(_, group) {
484
+ input.append(group);
485
+ });
486
+
487
+ // safe to set a select's value as per a normal input
488
+ input.val(options.value);
489
+ break;
490
+
491
+ case "checkbox":
492
+ var values = $.isArray(options.value) ? options.value : [options.value];
493
+ inputOptions = options.inputOptions || [];
494
+
495
+ if (!inputOptions.length) {
496
+ throw new Error("prompt with checkbox requires options");
497
+ }
498
+
499
+ if (!inputOptions[0].value || !inputOptions[0].text) {
500
+ throw new Error("given options in wrong format");
501
+ }
502
+
503
+ // checkboxes have to nest within a containing element, so
504
+ // they break the rules a bit and we end up re-assigning
505
+ // our 'input' element to this container instead
506
+ input = $("<div/>");
507
+
508
+ each(inputOptions, function(_, option) {
509
+ var checkbox = $(templates.inputs[options.inputType]);
510
+
511
+ checkbox.find("input").attr("value", option.value);
512
+ checkbox.find("label").append(option.text);
513
+
514
+ // we've ensured values is an array so we can always iterate over it
515
+ each(values, function(_, value) {
516
+ if (value === option.value) {
517
+ checkbox.find("input").prop("checked", true);
518
+ }
519
+ });
520
+
521
+ input.append(checkbox);
522
+ });
523
+ break;
524
+ }
525
+
526
+ // @TODO provide an attributes option instead
527
+ // and simply map that as keys: vals
528
+ if (options.placeholder) {
529
+ input.attr("placeholder", options.placeholder);
530
+ }
531
+
532
+ if (options.pattern) {
533
+ input.attr("pattern", options.pattern);
534
+ }
535
+
536
+ if (options.maxlength) {
537
+ input.attr("maxlength", options.maxlength);
538
+ }
539
+
540
+ // now place it in our form
541
+ form.append(input);
542
+
543
+ form.on("submit", function(e) {
544
+ e.preventDefault();
545
+ // Fix for SammyJS (or similar JS routing library) hijacking the form post.
546
+ e.stopPropagation();
547
+ // @TODO can we actually click *the* button object instead?
548
+ // e.g. buttons.confirm.click() or similar
549
+ dialog.find(".btn-primary").click();
550
+ });
551
+
552
+ dialog = exports.dialog(options);
553
+
554
+ // clear the existing handler focusing the submit button...
555
+ dialog.off("shown.bs.modal");
556
+
557
+ // ...and replace it with one focusing our input, if possible
558
+ dialog.on("shown.bs.modal", function() {
559
+ // need the closure here since input isn't
560
+ // an object otherwise
561
+ input.focus();
562
+ });
563
+
564
+ if (shouldShow === true) {
565
+ dialog.modal("show");
566
+ }
567
+
568
+ return dialog;
569
+ };
570
+
571
+ exports.dialog = function(options) {
572
+ options = sanitize(options);
573
+
574
+ var dialog = $(templates.dialog);
575
+ var innerDialog = dialog.find(".modal-dialog");
576
+ var body = dialog.find(".modal-body");
577
+ var buttons = options.buttons;
578
+ var buttonStr = "";
579
+ var callbacks = {
580
+ onEscape: options.onEscape
581
+ };
582
+
583
+ if ($.fn.modal === undefined) {
584
+ throw new Error(
585
+ "$.fn.modal is not defined; please double check you have included " +
586
+ "the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ " +
587
+ "for more details."
588
+ );
589
+ }
590
+
591
+ each(buttons, function(key, button) {
592
+
593
+ // @TODO I don't like this string appending to itself; bit dirty. Needs reworking
594
+ // can we just build up button elements instead? slower but neater. Then button
595
+ // can just become a template too
596
+ buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>";
597
+ callbacks[key] = button.callback;
598
+ });
599
+
600
+ body.find(".bootbox-body").html(options.message);
601
+
602
+ if (options.animate === true) {
603
+ dialog.addClass("fade");
604
+ }
605
+
606
+ if (options.className) {
607
+ dialog.addClass(options.className);
608
+ }
609
+
610
+ if (options.size === "large") {
611
+ innerDialog.addClass("modal-lg");
612
+ } else if (options.size === "small") {
613
+ innerDialog.addClass("modal-sm");
614
+ }
615
+
616
+ if (options.title) {
617
+ body.before(templates.header);
618
+ }
619
+
620
+ if (options.closeButton) {
621
+ var closeButton = $(templates.closeButton);
622
+
623
+ if (options.title) {
624
+ dialog.find(".modal-header").prepend(closeButton);
625
+ } else {
626
+ closeButton.css("margin-top", "-10px").prependTo(body);
627
+ }
628
+ }
629
+
630
+ if (options.title) {
631
+ dialog.find(".modal-title").html(options.title);
632
+ }
633
+
634
+ if (buttonStr.length) {
635
+ body.after(templates.footer);
636
+ dialog.find(".modal-footer").html(buttonStr);
637
+ }
638
+
639
+
640
+ /**
641
+ * Bootstrap event listeners; used handle extra
642
+ * setup & teardown required after the underlying
643
+ * modal has performed certain actions
644
+ */
645
+
646
+ dialog.on("hidden.bs.modal", function(e) {
647
+ // ensure we don't accidentally intercept hidden events triggered
648
+ // by children of the current dialog. We shouldn't anymore now BS
649
+ // namespaces its events; but still worth doing
650
+ if (e.target === this) {
651
+ dialog.remove();
652
+ }
653
+ });
654
+
655
+ /*
656
+ dialog.on("show.bs.modal", function() {
657
+ // sadly this doesn't work; show is called *just* before
658
+ // the backdrop is added so we'd need a setTimeout hack or
659
+ // otherwise... leaving in as would be nice
660
+ if (options.backdrop) {
661
+ dialog.next(".modal-backdrop").addClass("bootbox-backdrop");
662
+ }
663
+ });
664
+ */
665
+
666
+ dialog.on("shown.bs.modal", function() {
667
+ dialog.find(".btn-primary:first").focus();
668
+ });
669
+
670
+ /**
671
+ * Bootbox event listeners; experimental and may not last
672
+ * just an attempt to decouple some behaviours from their
673
+ * respective triggers
674
+ */
675
+
676
+ if (options.backdrop !== "static") {
677
+ // A boolean true/false according to the Bootstrap docs
678
+ // should show a dialog the user can dismiss by clicking on
679
+ // the background.
680
+ // We always only ever pass static/false to the actual
681
+ // $.modal function because with `true` we can't trap
682
+ // this event (the .modal-backdrop swallows it)
683
+ // However, we still want to sort of respect true
684
+ // and invoke the escape mechanism instead
685
+ dialog.on("click.dismiss.bs.modal", function(e) {
686
+ // @NOTE: the target varies in >= 3.3.x releases since the modal backdrop
687
+ // moved *inside* the outer dialog rather than *alongside* it
688
+ if (dialog.children(".modal-backdrop").length) {
689
+ e.currentTarget = dialog.children(".modal-backdrop").get(0);
690
+ }
691
+
692
+ if (e.target !== e.currentTarget) {
693
+ return;
694
+ }
695
+
696
+ dialog.trigger("escape.close.bb");
697
+ });
698
+ }
699
+
700
+ dialog.on("escape.close.bb", function(e) {
701
+ if (callbacks.onEscape) {
702
+ processCallback(e, dialog, callbacks.onEscape);
703
+ }
704
+ });
705
+
706
+ /**
707
+ * Standard jQuery event listeners; used to handle user
708
+ * interaction with our dialog
709
+ */
710
+
711
+ dialog.on("click", ".modal-footer button", function(e) {
712
+ var callbackKey = $(this).data("bb-handler");
713
+
714
+ processCallback(e, dialog, callbacks[callbackKey]);
715
+ });
716
+
717
+ dialog.on("click", ".bootbox-close-button", function(e) {
718
+ // onEscape might be falsy but that's fine; the fact is
719
+ // if the user has managed to click the close button we
720
+ // have to close the dialog, callback or not
721
+ processCallback(e, dialog, callbacks.onEscape);
722
+ });
723
+
724
+ dialog.on("keyup", function(e) {
725
+ if (e.which === 27) {
726
+ dialog.trigger("escape.close.bb");
727
+ }
728
+ });
729
+
730
+ // the remainder of this method simply deals with adding our
731
+ // dialogent to the DOM, augmenting it with Bootstrap's modal
732
+ // functionality and then giving the resulting object back
733
+ // to our caller
734
+
735
+ $(options.container).append(dialog);
736
+
737
+ dialog.modal({
738
+ backdrop: options.backdrop ? "static": false,
739
+ keyboard: false,
740
+ show: false
741
+ });
742
+
743
+ if (options.show) {
744
+ dialog.modal("show");
745
+ }
746
+
747
+ // @TODO should we return the raw element here or should
748
+ // we wrap it in an object on which we can expose some neater
749
+ // methods, e.g. var d = bootbox.alert(); d.hide(); instead
750
+ // of d.modal("hide");
751
+
752
+ /*
753
+ function BBDialog(elem) {
754
+ this.elem = elem;
755
+ }
756
+
757
+ BBDialog.prototype = {
758
+ hide: function() {
759
+ return this.elem.modal("hide");
760
+ },
761
+ show: function() {
762
+ return this.elem.modal("show");
763
+ }
764
+ };
765
+ */
766
+
767
+ return dialog;
768
+
769
+ };
770
+
771
+ exports.setDefaults = function() {
772
+ var values = {};
773
+
774
+ if (arguments.length === 2) {
775
+ // allow passing of single key/value...
776
+ values[arguments[0]] = arguments[1];
777
+ } else {
778
+ // ... and as an object too
779
+ values = arguments[0];
780
+ }
781
+
782
+ $.extend(defaults, values);
783
+ };
784
+
785
+ exports.hideAll = function() {
786
+ $(".bootbox").modal("hide");
787
+
788
+ return exports;
789
+ };
790
+
791
+
792
+ /**
793
+ * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are
794
+ * unlikely to be required. If this gets too large it can be split out into separate JS files.
795
+ */
796
+ var locales = {
797
+ bg_BG : {
798
+ OK : "Ок",
799
+ CANCEL : "Отказ",
800
+ CONFIRM : "Потвърждавам"
801
+ },
802
+ br : {
803
+ OK : "OK",
804
+ CANCEL : "Cancelar",
805
+ CONFIRM : "Sim"
806
+ },
807
+ cs : {
808
+ OK : "OK",
809
+ CANCEL : "Zrušit",
810
+ CONFIRM : "Potvrdit"
811
+ },
812
+ da : {
813
+ OK : "OK",
814
+ CANCEL : "Annuller",
815
+ CONFIRM : "Accepter"
816
+ },
817
+ de : {
818
+ OK : "OK",
819
+ CANCEL : "Abbrechen",
820
+ CONFIRM : "Akzeptieren"
821
+ },
822
+ el : {
823
+ OK : "Εντάξει",
824
+ CANCEL : "Ακύρωση",
825
+ CONFIRM : "Επιβεβαίωση"
826
+ },
827
+ en : {
828
+ OK : "OK",
829
+ CANCEL : "Cancel",
830
+ CONFIRM : "OK"
831
+ },
832
+ es : {
833
+ OK : "OK",
834
+ CANCEL : "Cancelar",
835
+ CONFIRM : "Aceptar"
836
+ },
837
+ et : {
838
+ OK : "OK",
839
+ CANCEL : "Katkesta",
840
+ CONFIRM : "OK"
841
+ },
842
+ fa : {
843
+ OK : "قبول",
844
+ CANCEL : "لغو",
845
+ CONFIRM : "تایید"
846
+ },
847
+ fi : {
848
+ OK : "OK",
849
+ CANCEL : "Peruuta",
850
+ CONFIRM : "OK"
851
+ },
852
+ fr : {
853
+ OK : "OK",
854
+ CANCEL : "Annuler",
855
+ CONFIRM : "D'accord"
856
+ },
857
+ he : {
858
+ OK : "אישור",
859
+ CANCEL : "ביטול",
860
+ CONFIRM : "אישור"
861
+ },
862
+ hu : {
863
+ OK : "OK",
864
+ CANCEL : "Mégsem",
865
+ CONFIRM : "Megerősít"
866
+ },
867
+ hr : {
868
+ OK : "OK",
869
+ CANCEL : "Odustani",
870
+ CONFIRM : "Potvrdi"
871
+ },
872
+ id : {
873
+ OK : "OK",
874
+ CANCEL : "Batal",
875
+ CONFIRM : "OK"
876
+ },
877
+ it : {
878
+ OK : "OK",
879
+ CANCEL : "Annulla",
880
+ CONFIRM : "Conferma"
881
+ },
882
+ ja : {
883
+ OK : "OK",
884
+ CANCEL : "キャンセル",
885
+ CONFIRM : "確認"
886
+ },
887
+ lt : {
888
+ OK : "Gerai",
889
+ CANCEL : "Atšaukti",
890
+ CONFIRM : "Patvirtinti"
891
+ },
892
+ lv : {
893
+ OK : "Labi",
894
+ CANCEL : "Atcelt",
895
+ CONFIRM : "Apstiprināt"
896
+ },
897
+ nl : {
898
+ OK : "OK",
899
+ CANCEL : "Annuleren",
900
+ CONFIRM : "Accepteren"
901
+ },
902
+ no : {
903
+ OK : "OK",
904
+ CANCEL : "Avbryt",
905
+ CONFIRM : "OK"
906
+ },
907
+ pl : {
908
+ OK : "OK",
909
+ CANCEL : "Anuluj",
910
+ CONFIRM : "Potwierdź"
911
+ },
912
+ pt : {
913
+ OK : "OK",
914
+ CANCEL : "Cancelar",
915
+ CONFIRM : "Confirmar"
916
+ },
917
+ ru : {
918
+ OK : "OK",
919
+ CANCEL : "Отмена",
920
+ CONFIRM : "Применить"
921
+ },
922
+ sq : {
923
+ OK : "OK",
924
+ CANCEL : "Anulo",
925
+ CONFIRM : "Prano"
926
+ },
927
+ sv : {
928
+ OK : "OK",
929
+ CANCEL : "Avbryt",
930
+ CONFIRM : "OK"
931
+ },
932
+ th : {
933
+ OK : "ตกลง",
934
+ CANCEL : "ยกเลิก",
935
+ CONFIRM : "ยืนยัน"
936
+ },
937
+ tr : {
938
+ OK : "Tamam",
939
+ CANCEL : "İptal",
940
+ CONFIRM : "Onayla"
941
+ },
942
+ zh_CN : {
943
+ OK : "OK",
944
+ CANCEL : "取消",
945
+ CONFIRM : "确认"
946
+ },
947
+ zh_TW : {
948
+ OK : "OK",
949
+ CANCEL : "取消",
950
+ CONFIRM : "確認"
951
+ }
952
+ };
953
+
954
+ exports.addLocale = function(name, values) {
955
+ $.each(["OK", "CANCEL", "CONFIRM"], function(_, v) {
956
+ if (!values[v]) {
957
+ throw new Error("Please supply a translation for '" + v + "'");
958
+ }
959
+ });
960
+
961
+ locales[name] = {
962
+ OK: values.OK,
963
+ CANCEL: values.CANCEL,
964
+ CONFIRM: values.CONFIRM
965
+ };
966
+
967
+ return exports;
968
+ };
969
+
970
+ exports.removeLocale = function(name) {
971
+ delete locales[name];
972
+
973
+ return exports;
974
+ };
975
+
976
+ exports.setLocale = function(name) {
977
+ return exports.setDefaults("locale", name);
978
+ };
979
+
980
+ exports.init = function(_$) {
981
+ return init(_$ || $);
982
+ };
983
+
984
+ return exports;
985
+ }));
@@ -0,0 +1,4 @@
1
+ # Component dependencies
2
+ Opal.use_gem('opal-bootbox')
3
+
4
+
@@ -0,0 +1,11 @@
1
+ # Place any code you want to run when the component is included on the client
2
+ # or server.
3
+
4
+ # To include code only on the client use:
5
+ # if RUBY_PLATFORM == 'opal'
6
+ #
7
+ # To include code only on the server, use:
8
+ # unless RUBY_PLATFORM == 'opal'
9
+ # ^^ this will not send compile in code in the conditional to the client.
10
+ # ^^ this include code required in the conditional.
11
+
@@ -0,0 +1 @@
1
+ # Component routes
@@ -0,0 +1,5 @@
1
+ module Volt
2
+ module Bootbox
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # If you need to require in code in the gem's app folder, keep in mind that
2
+ # the app is not on the load path when the gem is required. Use
3
+ # app/{gemname}/config/initializers/boot.rb to require in client or server
4
+ # code.
5
+ #
6
+ # Also, in volt apps, you typically use the lib folder in the
7
+ # app/{componentname} folder instead of this lib folder. This lib folder is
8
+ # for setting up gem code when Bundler.require is called. (or the gem is
9
+ # required.)
10
+ #
11
+ # If you need to configure volt in some way, you can add a Volt.configure block
12
+ # in this file.
13
+
14
+ require 'opal/bootbox'
15
+
16
+ module Volt
17
+ module Bootbox
18
+ module_function
19
+ extend Opal::Bootbox
20
+ end
21
+ end
data/make/build ADDED
@@ -0,0 +1,3 @@
1
+ sh make/commit
2
+ gem build volt-bootbox.gemspec
3
+ gem install volt-bootbox-0.1.0.gem
data/make/commit ADDED
@@ -0,0 +1,2 @@
1
+ git add -A
2
+ git commit -m "initial commit"
data/make/push ADDED
@@ -0,0 +1,5 @@
1
+ sh make/build
2
+ git remote add origin https://github.com/balmoral/volt-bootbox.git
3
+ git push -u origin master
4
+ git push
5
+ gem push volt-bootbox-0.1.0.gem
@@ -0,0 +1,14 @@
1
+ # Volt sets up rspec and capybara for testing.
2
+ require 'volt/spec/setup'
3
+ Volt.spec_setup
4
+
5
+ RSpec.configure do |config|
6
+ config.run_all_when_everything_filtered = true
7
+ config.filter_run :focus
8
+
9
+ # Run specs in random order to surface order dependencies. If you find an
10
+ # order dependency and want to debug it, you can fix the order by providing
11
+ # the seed, which is printed after each run.
12
+ # --seed 1234
13
+ config.order = 'random'
14
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Volt::Highcharts do
4
+ it 'should have a version number' do
5
+ expect(Volt::Highcharts::VERSION).not_to be nil
6
+ end
7
+
8
+ it 'should do something useful' do
9
+ expect(false).to be true
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ puts ">>>> lib=#{lib}"
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'volt/bootbox/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "volt-bootbox"
9
+ spec.version = Volt::Bootbox::VERSION
10
+ spec.authors = ["Colin Gunn"]
11
+ spec.email = ["colgunn@icloud.com"]
12
+ spec.summary = %q{Volt wrapper for Opal-Bootbox which in turn wraps Bootbox Javascript library.}
13
+ spec.description = %q{Volt wrapper for Opal-Bootbox which in turn wraps Bootbox Javascript library.}
14
+ spec.homepage = "https://github.com/balmoral/volt-bootbox"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.required_ruby_version = '>= 2.1'
23
+ spec.add_dependency 'opal-bootbox', '~> 0.1.0'
24
+
25
+ # spec.add_runtime_dependency "volt", "~> 0.9.5.pre3"
26
+ # spec.add_development_dependency 'rspec', '~> 3.2.0'
27
+ # spec.add_development_dependency "rake"
28
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: volt-bootbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Colin Gunn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: opal-bootbox
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.0
27
+ description: Volt wrapper for Opal-Bootbox which in turn wraps Bootbox Javascript
28
+ library.
29
+ email:
30
+ - colgunn@icloud.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".rspec"
36
+ - CHANGELOG.md
37
+ - Gemfile
38
+ - LICENSE.txt
39
+ - README.md
40
+ - Rakefile
41
+ - app/bootbox/assets/js/bootbox.js
42
+ - app/bootbox/config/dependencies.rb
43
+ - app/bootbox/config/initializers/boot.rb
44
+ - app/bootbox/config/routes.rb
45
+ - lib/volt/bootbox.rb
46
+ - lib/volt/bootbox/version.rb
47
+ - make/build
48
+ - make/commit
49
+ - make/push
50
+ - spec/spec_helper.rb
51
+ - spec/volt/highcharts_spec.rb
52
+ - volt-bootbox.gemspec
53
+ homepage: https://github.com/balmoral/volt-bootbox
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '2.1'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.4.6
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Volt wrapper for Opal-Bootbox which in turn wraps Bootbox Javascript library.
77
+ test_files:
78
+ - spec/spec_helper.rb
79
+ - spec/volt/highcharts_spec.rb
80
+ has_rdoc: