Commit 1011697610d4f9d3713c9a8f3968dfb6e330492e
1 parent
32936e5f
Exists in
master
Alert usando janela modal.
Showing
2 changed files
with
881 additions
and
4 deletions
Show diff stats
archetype/html-rest/src/main/resources/archetype-resources/src/main/webapp/js/controller/bookmark-list.js
1 | $(function() { | 1 | $(function() { |
2 | + | ||
3 | + // Carregando o menu na página home | ||
4 | + $("#menu").load("menu.html", function() { | ||
5 | + | ||
6 | + AuthProxy.getUser(getUserOk, getUserFailed); | ||
7 | + | ||
8 | + $("#logout").on("click", function() { | ||
9 | + sessionStorage.removeItem('credentials'); | ||
10 | + location.href = "home.html"; | ||
11 | + }); | ||
12 | + | ||
13 | + }); | ||
14 | + | ||
2 | $("#new").focus(); | 15 | $("#new").focus(); |
3 | 16 | ||
4 | $(document).ready(function() { | 17 | $(document).ready(function() { |
@@ -21,9 +34,14 @@ $(function() { | @@ -21,9 +34,14 @@ $(function() { | ||
21 | }); | 34 | }); |
22 | 35 | ||
23 | if (ids.length == 0) { | 36 | if (ids.length == 0) { |
24 | - alert('Nenhum registro selecionado'); | ||
25 | - } else if (confirm('Tem certeza que deseja apagar?')) { | ||
26 | - BookmarkProxy.remove(ids, removeOk, removeFailed); | 37 | + bootbox.alert({message: "Nenhum registro selecionado"}); |
38 | + } else { | ||
39 | + bootbox.confirm("Tem certeza que deseja apagar?", function(result) { | ||
40 | + console.log(result); | ||
41 | + if(result) { | ||
42 | + BookmarkProxy.remove(ids, removeOk, removeFailed); | ||
43 | + } | ||
44 | + }); | ||
27 | } | 45 | } |
28 | }); | 46 | }); |
29 | }); | 47 | }); |
@@ -84,4 +102,4 @@ function removeFailed(request) { | @@ -84,4 +102,4 @@ function removeFailed(request) { | ||
84 | default: | 102 | default: |
85 | break; | 103 | break; |
86 | } | 104 | } |
87 | -} | 105 | -} |
106 | +} | ||
88 | \ No newline at end of file | 107 | \ No newline at end of file |
archetype/html-rest/src/main/resources/archetype-resources/src/main/webapp/js/lib/bootbox.js
0 → 100644
@@ -0,0 +1,859 @@ | @@ -0,0 +1,859 @@ | ||
1 | +/** | ||
2 | + * bootbox.js [v4.2.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 modal-sm'>" + | ||
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'>×</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 | ||
75 | + backdrop: true, | ||
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(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 | + // we only support Bootstrap's "static" and false backdrop args | ||
152 | + // supporting true would mean you could dismiss the dialog without | ||
153 | + // explicitly interacting with it | ||
154 | + options.backdrop = options.backdrop ? "static" : false; | ||
155 | + | ||
156 | + buttons = options.buttons; | ||
157 | + | ||
158 | + total = getKeyLength(buttons); | ||
159 | + | ||
160 | + each(buttons, function(key, button, index) { | ||
161 | + | ||
162 | + if ($.isFunction(button)) { | ||
163 | + // short form, assume value is our callback. Since button | ||
164 | + // isn't an object it isn't a reference either so re-assign it | ||
165 | + button = buttons[key] = { | ||
166 | + callback: button | ||
167 | + }; | ||
168 | + } | ||
169 | + | ||
170 | + // before any further checks make sure by now button is the correct type | ||
171 | + if ($.type(button) !== "object") { | ||
172 | + throw new Error("button with key " + key + " must be an object"); | ||
173 | + } | ||
174 | + | ||
175 | + if (!button.label) { | ||
176 | + // the lack of an explicit label means we'll assume the key is good enough | ||
177 | + button.label = key; | ||
178 | + } | ||
179 | + | ||
180 | + if (!button.className) { | ||
181 | + if (total <= 2 && index === total-1) { | ||
182 | + // always add a primary to the main option in a two-button dialog | ||
183 | + button.className = "btn-primary"; | ||
184 | + } else { | ||
185 | + button.className = "btn-default"; | ||
186 | + } | ||
187 | + } | ||
188 | + }); | ||
189 | + | ||
190 | + return options; | ||
191 | + } | ||
192 | + | ||
193 | + /** | ||
194 | + * map a flexible set of arguments into a single returned object | ||
195 | + * if args.length is already one just return it, otherwise | ||
196 | + * use the properties argument to map the unnamed args to | ||
197 | + * object properties | ||
198 | + * so in the latter case: | ||
199 | + * mapArguments(["foo", $.noop], ["message", "callback"]) | ||
200 | + * -> { message: "foo", callback: $.noop } | ||
201 | + */ | ||
202 | + function mapArguments(args, properties) { | ||
203 | + var argn = args.length; | ||
204 | + var options = {}; | ||
205 | + | ||
206 | + if (argn < 1 || argn > 2) { | ||
207 | + throw new Error("Invalid argument length"); | ||
208 | + } | ||
209 | + | ||
210 | + if (argn === 2 || typeof args[0] === "string") { | ||
211 | + options[properties[0]] = args[0]; | ||
212 | + options[properties[1]] = args[1]; | ||
213 | + } else { | ||
214 | + options = args[0]; | ||
215 | + } | ||
216 | + | ||
217 | + return options; | ||
218 | + } | ||
219 | + | ||
220 | + /** | ||
221 | + * merge a set of default dialog options with user supplied arguments | ||
222 | + */ | ||
223 | + function mergeArguments(defaults, args, properties) { | ||
224 | + return $.extend( | ||
225 | + // deep merge | ||
226 | + true, | ||
227 | + // ensure the target is an empty, unreferenced object | ||
228 | + {}, | ||
229 | + // the base options object for this type of dialog (often just buttons) | ||
230 | + defaults, | ||
231 | + // args could be an object or array; if it's an array properties will | ||
232 | + // map it to a proper options object | ||
233 | + mapArguments( | ||
234 | + args, | ||
235 | + properties | ||
236 | + ) | ||
237 | + ); | ||
238 | + } | ||
239 | + | ||
240 | + /** | ||
241 | + * this entry-level method makes heavy use of composition to take a simple | ||
242 | + * range of inputs and return valid options suitable for passing to bootbox.dialog | ||
243 | + */ | ||
244 | + function mergeDialogOptions(className, labels, properties, args) { | ||
245 | + // build up a base set of dialog properties | ||
246 | + var baseOptions = { | ||
247 | + className: "bootbox-" + className, | ||
248 | + buttons: createLabels.apply(null, labels) | ||
249 | + }; | ||
250 | + | ||
251 | + // ensure the buttons properties generated, *after* merging | ||
252 | + // with user args are still valid against the supplied labels | ||
253 | + return validateButtons( | ||
254 | + // merge the generated base properties with user supplied arguments | ||
255 | + mergeArguments( | ||
256 | + baseOptions, | ||
257 | + args, | ||
258 | + // if args.length > 1, properties specify how each arg maps to an object key | ||
259 | + properties | ||
260 | + ), | ||
261 | + labels | ||
262 | + ); | ||
263 | + } | ||
264 | + | ||
265 | + /** | ||
266 | + * from a given list of arguments return a suitable object of button labels | ||
267 | + * all this does is normalise the given labels and translate them where possible | ||
268 | + * e.g. "ok", "confirm" -> { ok: "OK, cancel: "Annuleren" } | ||
269 | + */ | ||
270 | + function createLabels() { | ||
271 | + var buttons = {}; | ||
272 | + | ||
273 | + for (var i = 0, j = arguments.length; i < j; i++) { | ||
274 | + var argument = arguments[i]; | ||
275 | + var key = argument.toLowerCase(); | ||
276 | + var value = argument.toUpperCase(); | ||
277 | + | ||
278 | + buttons[key] = { | ||
279 | + label: _t(value) | ||
280 | + }; | ||
281 | + } | ||
282 | + | ||
283 | + return buttons; | ||
284 | + } | ||
285 | + | ||
286 | + function validateButtons(options, buttons) { | ||
287 | + var allowedButtons = {}; | ||
288 | + each(buttons, function(key, value) { | ||
289 | + allowedButtons[value] = true; | ||
290 | + }); | ||
291 | + | ||
292 | + each(options.buttons, function(key) { | ||
293 | + if (allowedButtons[key] === undefined) { | ||
294 | + throw new Error("button key " + key + " is not allowed (options are " + buttons.join("\n") + ")"); | ||
295 | + } | ||
296 | + }); | ||
297 | + | ||
298 | + return options; | ||
299 | + } | ||
300 | + | ||
301 | + exports.alert = function() { | ||
302 | + var options; | ||
303 | + | ||
304 | + options = mergeDialogOptions("alert", ["ok"], ["message", "callback"], arguments); | ||
305 | + | ||
306 | + if (options.callback && !$.isFunction(options.callback)) { | ||
307 | + throw new Error("alert requires callback property to be a function when provided"); | ||
308 | + } | ||
309 | + | ||
310 | + /** | ||
311 | + * overrides | ||
312 | + */ | ||
313 | + options.buttons.ok.callback = options.onEscape = function() { | ||
314 | + if ($.isFunction(options.callback)) { | ||
315 | + return options.callback(); | ||
316 | + } | ||
317 | + return true; | ||
318 | + }; | ||
319 | + | ||
320 | + return exports.dialog(options); | ||
321 | + }; | ||
322 | + | ||
323 | + exports.confirm = function() { | ||
324 | + var options; | ||
325 | + | ||
326 | + options = mergeDialogOptions("confirm", ["cancel", "confirm"], ["message", "callback"], arguments); | ||
327 | + | ||
328 | + /** | ||
329 | + * overrides; undo anything the user tried to set they shouldn't have | ||
330 | + */ | ||
331 | + options.buttons.cancel.callback = options.onEscape = function() { | ||
332 | + return options.callback(false); | ||
333 | + }; | ||
334 | + | ||
335 | + options.buttons.confirm.callback = function() { | ||
336 | + return options.callback(true); | ||
337 | + }; | ||
338 | + | ||
339 | + // confirm specific validation | ||
340 | + if (!$.isFunction(options.callback)) { | ||
341 | + throw new Error("confirm requires a callback"); | ||
342 | + } | ||
343 | + | ||
344 | + return exports.dialog(options); | ||
345 | + }; | ||
346 | + | ||
347 | + exports.prompt = function() { | ||
348 | + var options; | ||
349 | + var defaults; | ||
350 | + var dialog; | ||
351 | + var form; | ||
352 | + var input; | ||
353 | + var shouldShow; | ||
354 | + var inputOptions; | ||
355 | + | ||
356 | + // we have to create our form first otherwise | ||
357 | + // its value is undefined when gearing up our options | ||
358 | + // @TODO this could be solved by allowing message to | ||
359 | + // be a function instead... | ||
360 | + form = $(templates.form); | ||
361 | + | ||
362 | + // prompt defaults are more complex than others in that | ||
363 | + // users can override more defaults | ||
364 | + // @TODO I don't like that prompt has to do a lot of heavy | ||
365 | + // lifting which mergeDialogOptions can *almost* support already | ||
366 | + // just because of 'value' and 'inputType' - can we refactor? | ||
367 | + defaults = { | ||
368 | + className: "bootbox-prompt", | ||
369 | + buttons: createLabels("cancel", "confirm"), | ||
370 | + value: "", | ||
371 | + inputType: "text" | ||
372 | + }; | ||
373 | + | ||
374 | + options = validateButtons( | ||
375 | + mergeArguments(defaults, arguments, ["title", "callback"]), | ||
376 | + ["cancel", "confirm"] | ||
377 | + ); | ||
378 | + | ||
379 | + // capture the user's show value; we always set this to false before | ||
380 | + // spawning the dialog to give us a chance to attach some handlers to | ||
381 | + // it, but we need to make sure we respect a preference not to show it | ||
382 | + shouldShow = (options.show === undefined) ? true : options.show; | ||
383 | + | ||
384 | + // check if the browser supports the option.inputType | ||
385 | + var html5inputs = ["date","time","number"]; | ||
386 | + var i = document.createElement("input"); | ||
387 | + i.setAttribute("type", options.inputType); | ||
388 | + if(html5inputs[options.inputType]){ | ||
389 | + options.inputType = i.type; | ||
390 | + } | ||
391 | + | ||
392 | + /** | ||
393 | + * overrides; undo anything the user tried to set they shouldn't have | ||
394 | + */ | ||
395 | + options.message = form; | ||
396 | + | ||
397 | + options.buttons.cancel.callback = options.onEscape = function() { | ||
398 | + return options.callback(null); | ||
399 | + }; | ||
400 | + | ||
401 | + options.buttons.confirm.callback = function() { | ||
402 | + var value; | ||
403 | + | ||
404 | + switch (options.inputType) { | ||
405 | + case "text": | ||
406 | + case "textarea": | ||
407 | + case "email": | ||
408 | + case "select": | ||
409 | + case "date": | ||
410 | + case "time": | ||
411 | + case "number": | ||
412 | + case "password": | ||
413 | + value = input.val(); | ||
414 | + break; | ||
415 | + | ||
416 | + case "checkbox": | ||
417 | + var checkedItems = input.find("input:checked"); | ||
418 | + | ||
419 | + // we assume that checkboxes are always multiple, | ||
420 | + // hence we default to an empty array | ||
421 | + value = []; | ||
422 | + | ||
423 | + each(checkedItems, function(_, item) { | ||
424 | + value.push($(item).val()); | ||
425 | + }); | ||
426 | + break; | ||
427 | + } | ||
428 | + | ||
429 | + return options.callback(value); | ||
430 | + }; | ||
431 | + | ||
432 | + options.show = false; | ||
433 | + | ||
434 | + // prompt specific validation | ||
435 | + if (!options.title) { | ||
436 | + throw new Error("prompt requires a title"); | ||
437 | + } | ||
438 | + | ||
439 | + if (!$.isFunction(options.callback)) { | ||
440 | + throw new Error("prompt requires a callback"); | ||
441 | + } | ||
442 | + | ||
443 | + if (!templates.inputs[options.inputType]) { | ||
444 | + throw new Error("invalid prompt type"); | ||
445 | + } | ||
446 | + | ||
447 | + // create the input based on the supplied type | ||
448 | + input = $(templates.inputs[options.inputType]); | ||
449 | + | ||
450 | + switch (options.inputType) { | ||
451 | + case "text": | ||
452 | + case "textarea": | ||
453 | + case "email": | ||
454 | + case "date": | ||
455 | + case "time": | ||
456 | + case "number": | ||
457 | + case "password": | ||
458 | + input.val(options.value); | ||
459 | + break; | ||
460 | + | ||
461 | + case "select": | ||
462 | + var groups = {}; | ||
463 | + inputOptions = options.inputOptions || []; | ||
464 | + | ||
465 | + if (!inputOptions.length) { | ||
466 | + throw new Error("prompt with select requires options"); | ||
467 | + } | ||
468 | + | ||
469 | + each(inputOptions, function(_, option) { | ||
470 | + | ||
471 | + // assume the element to attach to is the input... | ||
472 | + var elem = input; | ||
473 | + | ||
474 | + if (option.value === undefined || option.text === undefined) { | ||
475 | + throw new Error("given options in wrong format"); | ||
476 | + } | ||
477 | + | ||
478 | + | ||
479 | + // ... but override that element if this option sits in a group | ||
480 | + | ||
481 | + if (option.group) { | ||
482 | + // initialise group if necessary | ||
483 | + if (!groups[option.group]) { | ||
484 | + groups[option.group] = $("<optgroup/>").attr("label", option.group); | ||
485 | + } | ||
486 | + | ||
487 | + elem = groups[option.group]; | ||
488 | + } | ||
489 | + | ||
490 | + elem.append("<option value='" + option.value + "'>" + option.text + "</option>"); | ||
491 | + }); | ||
492 | + | ||
493 | + each(groups, function(_, group) { | ||
494 | + input.append(group); | ||
495 | + }); | ||
496 | + | ||
497 | + // safe to set a select's value as per a normal input | ||
498 | + input.val(options.value); | ||
499 | + break; | ||
500 | + | ||
501 | + case "checkbox": | ||
502 | + var values = $.isArray(options.value) ? options.value : [options.value]; | ||
503 | + inputOptions = options.inputOptions || []; | ||
504 | + | ||
505 | + if (!inputOptions.length) { | ||
506 | + throw new Error("prompt with checkbox requires options"); | ||
507 | + } | ||
508 | + | ||
509 | + if (!inputOptions[0].value || !inputOptions[0].text) { | ||
510 | + throw new Error("given options in wrong format"); | ||
511 | + } | ||
512 | + | ||
513 | + // checkboxes have to nest within a containing element, so | ||
514 | + // they break the rules a bit and we end up re-assigning | ||
515 | + // our 'input' element to this container instead | ||
516 | + input = $("<div/>"); | ||
517 | + | ||
518 | + each(inputOptions, function(_, option) { | ||
519 | + var checkbox = $(templates.inputs[options.inputType]); | ||
520 | + | ||
521 | + checkbox.find("input").attr("value", option.value); | ||
522 | + checkbox.find("label").append(option.text); | ||
523 | + | ||
524 | + // we've ensured values is an array so we can always iterate over it | ||
525 | + each(values, function(_, value) { | ||
526 | + if (value === option.value) { | ||
527 | + checkbox.find("input").prop("checked", true); | ||
528 | + } | ||
529 | + }); | ||
530 | + | ||
531 | + input.append(checkbox); | ||
532 | + }); | ||
533 | + break; | ||
534 | + } | ||
535 | + | ||
536 | + if (options.placeholder) { | ||
537 | + input.attr("placeholder", options.placeholder); | ||
538 | + } | ||
539 | + | ||
540 | + if(options.pattern){ | ||
541 | + input.attr("pattern", options.pattern); | ||
542 | + } | ||
543 | + | ||
544 | + // now place it in our form | ||
545 | + form.append(input); | ||
546 | + | ||
547 | + form.on("submit", function(e) { | ||
548 | + e.preventDefault(); | ||
549 | + // @TODO can we actually click *the* button object instead? | ||
550 | + // e.g. buttons.confirm.click() or similar | ||
551 | + dialog.find(".btn-primary").click(); | ||
552 | + }); | ||
553 | + | ||
554 | + dialog = exports.dialog(options); | ||
555 | + | ||
556 | + // clear the existing handler focusing the submit button... | ||
557 | + dialog.off("shown.bs.modal"); | ||
558 | + | ||
559 | + // ...and replace it with one focusing our input, if possible | ||
560 | + dialog.on("shown.bs.modal", function() { | ||
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 body = dialog.find(".modal-body"); | ||
576 | + var buttons = options.buttons; | ||
577 | + var buttonStr = ""; | ||
578 | + var callbacks = { | ||
579 | + onEscape: options.onEscape | ||
580 | + }; | ||
581 | + | ||
582 | + each(buttons, function(key, button) { | ||
583 | + | ||
584 | + // @TODO I don't like this string appending to itself; bit dirty. Needs reworking | ||
585 | + // can we just build up button elements instead? slower but neater. Then button | ||
586 | + // can just become a template too | ||
587 | + buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>"; | ||
588 | + callbacks[key] = button.callback; | ||
589 | + }); | ||
590 | + | ||
591 | + body.find(".bootbox-body").html(options.message); | ||
592 | + | ||
593 | + if (options.animate === true) { | ||
594 | + dialog.addClass("fade"); | ||
595 | + } | ||
596 | + | ||
597 | + if (options.className) { | ||
598 | + dialog.addClass(options.className); | ||
599 | + } | ||
600 | + | ||
601 | + if (options.title) { | ||
602 | + body.before(templates.header); | ||
603 | + } | ||
604 | + | ||
605 | + if (options.closeButton) { | ||
606 | + var closeButton = $(templates.closeButton); | ||
607 | + | ||
608 | + if (options.title) { | ||
609 | + dialog.find(".modal-header").prepend(closeButton); | ||
610 | + } else { | ||
611 | + closeButton.css("margin-top", "-10px").prependTo(body); | ||
612 | + } | ||
613 | + } | ||
614 | + | ||
615 | + if (options.title) { | ||
616 | + dialog.find(".modal-title").html(options.title); | ||
617 | + } | ||
618 | + | ||
619 | + if (buttonStr.length) { | ||
620 | + body.after(templates.footer); | ||
621 | + dialog.find(".modal-footer").html(buttonStr); | ||
622 | + } | ||
623 | + | ||
624 | + | ||
625 | + /** | ||
626 | + * Bootstrap event listeners; used handle extra | ||
627 | + * setup & teardown required after the underlying | ||
628 | + * modal has performed certain actions | ||
629 | + */ | ||
630 | + | ||
631 | + dialog.on("hidden.bs.modal", function(e) { | ||
632 | + // ensure we don't accidentally intercept hidden events triggered | ||
633 | + // by children of the current dialog. We shouldn't anymore now BS | ||
634 | + // namespaces its events; but still worth doing | ||
635 | + if (e.target === this) { | ||
636 | + dialog.remove(); | ||
637 | + } | ||
638 | + }); | ||
639 | + | ||
640 | + /* | ||
641 | + dialog.on("show.bs.modal", function() { | ||
642 | + // sadly this doesn't work; show is called *just* before | ||
643 | + // the backdrop is added so we'd need a setTimeout hack or | ||
644 | + // otherwise... leaving in as would be nice | ||
645 | + if (options.backdrop) { | ||
646 | + dialog.next(".modal-backdrop").addClass("bootbox-backdrop"); | ||
647 | + } | ||
648 | + }); | ||
649 | + */ | ||
650 | + | ||
651 | + dialog.on("shown.bs.modal", function() { | ||
652 | + dialog.find(".btn-primary:first").focus(); | ||
653 | + }); | ||
654 | + | ||
655 | + /** | ||
656 | + * Bootbox event listeners; experimental and may not last | ||
657 | + * just an attempt to decouple some behaviours from their | ||
658 | + * respective triggers | ||
659 | + */ | ||
660 | + | ||
661 | + dialog.on("escape.close.bb", function(e) { | ||
662 | + if (callbacks.onEscape) { | ||
663 | + processCallback(e, dialog, callbacks.onEscape); | ||
664 | + } | ||
665 | + }); | ||
666 | + | ||
667 | + /** | ||
668 | + * Standard jQuery event listeners; used to handle user | ||
669 | + * interaction with our dialog | ||
670 | + */ | ||
671 | + | ||
672 | + dialog.on("click", ".modal-footer button", function(e) { | ||
673 | + var callbackKey = $(this).data("bb-handler"); | ||
674 | + | ||
675 | + processCallback(e, dialog, callbacks[callbackKey]); | ||
676 | + | ||
677 | + }); | ||
678 | + | ||
679 | + dialog.on("click", ".bootbox-close-button", function(e) { | ||
680 | + // onEscape might be falsy but that's fine; the fact is | ||
681 | + // if the user has managed to click the close button we | ||
682 | + // have to close the dialog, callback or not | ||
683 | + processCallback(e, dialog, callbacks.onEscape); | ||
684 | + }); | ||
685 | + | ||
686 | + dialog.on("keyup", function(e) { | ||
687 | + if (e.which === 27) { | ||
688 | + dialog.trigger("escape.close.bb"); | ||
689 | + } | ||
690 | + }); | ||
691 | + | ||
692 | + // the remainder of this method simply deals with adding our | ||
693 | + // dialogent to the DOM, augmenting it with Bootstrap's modal | ||
694 | + // functionality and then giving the resulting object back | ||
695 | + // to our caller | ||
696 | + | ||
697 | + $(options.container).append(dialog); | ||
698 | + | ||
699 | + dialog.modal({ | ||
700 | + backdrop: options.backdrop, | ||
701 | + keyboard: false, | ||
702 | + show: false | ||
703 | + }); | ||
704 | + | ||
705 | + if (options.show) { | ||
706 | + dialog.modal("show"); | ||
707 | + } | ||
708 | + | ||
709 | + // @TODO should we return the raw element here or should | ||
710 | + // we wrap it in an object on which we can expose some neater | ||
711 | + // methods, e.g. var d = bootbox.alert(); d.hide(); instead | ||
712 | + // of d.modal("hide"); | ||
713 | + | ||
714 | + /* | ||
715 | + function BBDialog(elem) { | ||
716 | + this.elem = elem; | ||
717 | + } | ||
718 | + | ||
719 | + BBDialog.prototype = { | ||
720 | + hide: function() { | ||
721 | + return this.elem.modal("hide"); | ||
722 | + }, | ||
723 | + show: function() { | ||
724 | + return this.elem.modal("show"); | ||
725 | + } | ||
726 | + }; | ||
727 | + */ | ||
728 | + | ||
729 | + return dialog; | ||
730 | + | ||
731 | + }; | ||
732 | + | ||
733 | + exports.setDefaults = function() { | ||
734 | + var values = {}; | ||
735 | + | ||
736 | + if (arguments.length === 2) { | ||
737 | + // allow passing of single key/value... | ||
738 | + values[arguments[0]] = arguments[1]; | ||
739 | + } else { | ||
740 | + // ... and as an object too | ||
741 | + values = arguments[0]; | ||
742 | + } | ||
743 | + | ||
744 | + $.extend(defaults, values); | ||
745 | + }; | ||
746 | + | ||
747 | + exports.hideAll = function() { | ||
748 | + $(".bootbox").modal("hide"); | ||
749 | + }; | ||
750 | + | ||
751 | + | ||
752 | + /** | ||
753 | + * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are | ||
754 | + * unlikely to be required. If this gets too large it can be split out into separate JS files. | ||
755 | + */ | ||
756 | + var locales = { | ||
757 | + br : { | ||
758 | + OK : "OK", | ||
759 | + CANCEL : "Cancelar", | ||
760 | + CONFIRM : "Sim" | ||
761 | + }, | ||
762 | + da : { | ||
763 | + OK : "OK", | ||
764 | + CANCEL : "Annuller", | ||
765 | + CONFIRM : "Accepter" | ||
766 | + }, | ||
767 | + de : { | ||
768 | + OK : "OK", | ||
769 | + CANCEL : "Abbrechen", | ||
770 | + CONFIRM : "Akzeptieren" | ||
771 | + }, | ||
772 | + en : { | ||
773 | + OK : "OK", | ||
774 | + CANCEL : "Cancel", | ||
775 | + CONFIRM : "OK" | ||
776 | + }, | ||
777 | + es : { | ||
778 | + OK : "OK", | ||
779 | + CANCEL : "Cancelar", | ||
780 | + CONFIRM : "Aceptar" | ||
781 | + }, | ||
782 | + fi : { | ||
783 | + OK : "OK", | ||
784 | + CANCEL : "Peruuta", | ||
785 | + CONFIRM : "OK" | ||
786 | + }, | ||
787 | + fr : { | ||
788 | + OK : "OK", | ||
789 | + CANCEL : "Annuler", | ||
790 | + CONFIRM : "D'accord" | ||
791 | + }, | ||
792 | + he : { | ||
793 | + OK : "אישור", | ||
794 | + CANCEL : "ביטול", | ||
795 | + CONFIRM : "אישור" | ||
796 | + }, | ||
797 | + it : { | ||
798 | + OK : "OK", | ||
799 | + CANCEL : "Annulla", | ||
800 | + CONFIRM : "Conferma" | ||
801 | + }, | ||
802 | + lt : { | ||
803 | + OK : "Gerai", | ||
804 | + CANCEL : "Atšaukti", | ||
805 | + CONFIRM : "Patvirtinti" | ||
806 | + }, | ||
807 | + lv : { | ||
808 | + OK : "Labi", | ||
809 | + CANCEL : "Atcelt", | ||
810 | + CONFIRM : "Apstiprināt" | ||
811 | + }, | ||
812 | + nl : { | ||
813 | + OK : "OK", | ||
814 | + CANCEL : "Annuleren", | ||
815 | + CONFIRM : "Accepteren" | ||
816 | + }, | ||
817 | + no : { | ||
818 | + OK : "OK", | ||
819 | + CANCEL : "Avbryt", | ||
820 | + CONFIRM : "OK" | ||
821 | + }, | ||
822 | + pl : { | ||
823 | + OK : "OK", | ||
824 | + CANCEL : "Anuluj", | ||
825 | + CONFIRM : "Potwierdź" | ||
826 | + }, | ||
827 | + ru : { | ||
828 | + OK : "OK", | ||
829 | + CANCEL : "Отмена", | ||
830 | + CONFIRM : "Применить" | ||
831 | + }, | ||
832 | + sv : { | ||
833 | + OK : "OK", | ||
834 | + CANCEL : "Avbryt", | ||
835 | + CONFIRM : "OK" | ||
836 | + }, | ||
837 | + tr : { | ||
838 | + OK : "Tamam", | ||
839 | + CANCEL : "İptal", | ||
840 | + CONFIRM : "Onayla" | ||
841 | + }, | ||
842 | + zh_CN : { | ||
843 | + OK : "OK", | ||
844 | + CANCEL : "取消", | ||
845 | + CONFIRM : "确认" | ||
846 | + }, | ||
847 | + zh_TW : { | ||
848 | + OK : "OK", | ||
849 | + CANCEL : "取消", | ||
850 | + CONFIRM : "確認" | ||
851 | + } | ||
852 | + }; | ||
853 | + | ||
854 | + exports.init = function(_$) { | ||
855 | + return init(_$ || $); | ||
856 | + }; | ||
857 | + | ||
858 | + return exports; | ||
859 | +})); |