volt-bootbox 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: