bootbox.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. /**
  2. * bootbox.js [v4.4.0]
  3. *
  4. * http://bootboxjs.com/license.txt
  5. */
  6. // @see https://github.com/makeusabrew/bootbox/issues/180
  7. // @see https://github.com/makeusabrew/bootbox/issues/186
  8. (function (root, factory) {
  9. "use strict";
  10. if (typeof define === "function" && define.amd) {
  11. // AMD. Register as an anonymous module.
  12. define(["jquery"], factory);
  13. } else if (typeof exports === "object") {
  14. // Node. Does not work with strict CommonJS, but
  15. // only CommonJS-like environments that support module.exports,
  16. // like Node.
  17. module.exports = factory(require("jquery"));
  18. } else {
  19. // Browser globals (root is window)
  20. root.bootbox = factory(root.jQuery);
  21. }
  22. }(this, function init($, undefined) {
  23. "use strict";
  24. // the base DOM structure needed to create a modal
  25. var templates = {
  26. dialog:
  27. "<div class='bootbox modal' tabindex='-1' role='dialog'>" +
  28. "<div class='modal-dialog'>" +
  29. "<div class='modal-content'>" +
  30. "<div class='modal-body'><div class='bootbox-body'></div></div>" +
  31. "</div>" +
  32. "</div>" +
  33. "</div>",
  34. header:
  35. "<div class='modal-header'>" +
  36. "<h4 class='modal-title'></h4>" +
  37. "</div>",
  38. footer:
  39. "<div class='modal-footer'></div>",
  40. closeButton:
  41. "<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>&times;</button>",
  42. form:
  43. "<form class='bootbox-form'></form>",
  44. inputs: {
  45. text:
  46. "<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",
  47. textarea:
  48. "<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",
  49. email:
  50. "<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",
  51. select:
  52. "<select class='bootbox-input bootbox-input-select form-control'></select>",
  53. checkbox:
  54. "<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",
  55. date:
  56. "<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",
  57. time:
  58. "<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",
  59. number:
  60. "<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",
  61. password:
  62. "<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"
  63. }
  64. };
  65. var defaults = {
  66. // default language
  67. locale: "en",
  68. // show backdrop or not. Default to static so user has to interact with dialog
  69. backdrop: "static",
  70. // animate the modal in/out
  71. animate: true,
  72. // additional class string applied to the top level dialog
  73. className: null,
  74. // whether or not to include a close button
  75. closeButton: true,
  76. // show the dialog immediately by default
  77. show: true,
  78. // dialog container
  79. container: "body"
  80. };
  81. // our public object; augmented after our private API
  82. var exports = {};
  83. /**
  84. * @private
  85. */
  86. function _t(key) {
  87. var locale = locales[defaults.locale];
  88. return locale ? locale[key] : locales.en[key];
  89. }
  90. function processCallback(e, dialog, callback) {
  91. e.stopPropagation();
  92. e.preventDefault();
  93. // by default we assume a callback will get rid of the dialog,
  94. // although it is given the opportunity to override this
  95. // so, if the callback can be invoked and it *explicitly returns false*
  96. // then we'll set a flag to keep the dialog active...
  97. var preserveDialog = $.isFunction(callback) && callback.call(dialog, e) === false;
  98. // ... otherwise we'll bin it
  99. if (!preserveDialog) {
  100. dialog.modal("hide");
  101. }
  102. }
  103. function getKeyLength(obj) {
  104. // @TODO defer to Object.keys(x).length if available?
  105. var k, t = 0;
  106. for (k in obj) {
  107. t ++;
  108. }
  109. return t;
  110. }
  111. function each(collection, iterator) {
  112. var index = 0;
  113. $.each(collection, function(key, value) {
  114. iterator(key, value, index++);
  115. });
  116. }
  117. function sanitize(options) {
  118. var buttons;
  119. var total;
  120. if (typeof options !== "object") {
  121. throw new Error("Please supply an object of options");
  122. }
  123. if (!options.message) {
  124. throw new Error("Please specify a message");
  125. }
  126. // make sure any supplied options take precedence over defaults
  127. options = $.extend({}, defaults, options);
  128. if (!options.buttons) {
  129. options.buttons = {};
  130. }
  131. buttons = options.buttons;
  132. total = getKeyLength(buttons);
  133. each(buttons, function(key, button, index) {
  134. if ($.isFunction(button)) {
  135. // short form, assume value is our callback. Since button
  136. // isn't an object it isn't a reference either so re-assign it
  137. button = buttons[key] = {
  138. callback: button
  139. };
  140. }
  141. // before any further checks make sure by now button is the correct type
  142. if ($.type(button) !== "object") {
  143. throw new Error("button with key " + key + " must be an object");
  144. }
  145. if (!button.label) {
  146. // the lack of an explicit label means we'll assume the key is good enough
  147. button.label = key;
  148. }
  149. if (!button.className) {
  150. if (total <= 2 && index === total-1) {
  151. // always add a primary to the main option in a two-button dialog
  152. button.className = "btn-primary";
  153. } else {
  154. button.className = "btn-default";
  155. }
  156. }
  157. });
  158. return options;
  159. }
  160. /**
  161. * map a flexible set of arguments into a single returned object
  162. * if args.length is already one just return it, otherwise
  163. * use the properties argument to map the unnamed args to
  164. * object properties
  165. * so in the latter case:
  166. * mapArguments(["foo", $.noop], ["message", "callback"])
  167. * -> { message: "foo", callback: $.noop }
  168. */
  169. function mapArguments(args, properties) {
  170. var argn = args.length;
  171. var options = {};
  172. if (argn < 1 || argn > 2) {
  173. throw new Error("Invalid argument length");
  174. }
  175. if (argn === 2 || typeof args[0] === "string") {
  176. options[properties[0]] = args[0];
  177. options[properties[1]] = args[1];
  178. } else {
  179. options = args[0];
  180. }
  181. return options;
  182. }
  183. /**
  184. * merge a set of default dialog options with user supplied arguments
  185. */
  186. function mergeArguments(defaults, args, properties) {
  187. return $.extend(
  188. // deep merge
  189. true,
  190. // ensure the target is an empty, unreferenced object
  191. {},
  192. // the base options object for this type of dialog (often just buttons)
  193. defaults,
  194. // args could be an object or array; if it's an array properties will
  195. // map it to a proper options object
  196. mapArguments(
  197. args,
  198. properties
  199. )
  200. );
  201. }
  202. /**
  203. * this entry-level method makes heavy use of composition to take a simple
  204. * range of inputs and return valid options suitable for passing to bootbox.dialog
  205. */
  206. function mergeDialogOptions(className, labels, properties, args) {
  207. // build up a base set of dialog properties
  208. var baseOptions = {
  209. className: "bootbox-" + className,
  210. buttons: createLabels.apply(null, labels)
  211. };
  212. // ensure the buttons properties generated, *after* merging
  213. // with user args are still valid against the supplied labels
  214. return validateButtons(
  215. // merge the generated base properties with user supplied arguments
  216. mergeArguments(
  217. baseOptions,
  218. args,
  219. // if args.length > 1, properties specify how each arg maps to an object key
  220. properties
  221. ),
  222. labels
  223. );
  224. }
  225. /**
  226. * from a given list of arguments return a suitable object of button labels
  227. * all this does is normalise the given labels and translate them where possible
  228. * e.g. "ok", "confirm" -> { ok: "OK, cancel: "Annuleren" }
  229. */
  230. function createLabels() {
  231. var buttons = {};
  232. for (var i = 0, j = arguments.length; i < j; i++) {
  233. var argument = arguments[i];
  234. var key = argument.toLowerCase();
  235. var value = argument.toUpperCase();
  236. buttons[key] = {
  237. label: _t(value)
  238. };
  239. }
  240. return buttons;
  241. }
  242. function validateButtons(options, buttons) {
  243. var allowedButtons = {};
  244. each(buttons, function(key, value) {
  245. allowedButtons[value] = true;
  246. });
  247. each(options.buttons, function(key) {
  248. if (allowedButtons[key] === undefined) {
  249. throw new Error("button key " + key + " is not allowed (options are " + buttons.join("\n") + ")");
  250. }
  251. });
  252. return options;
  253. }
  254. exports.alert = function() {
  255. var options;
  256. options = mergeDialogOptions("alert", ["ok"], ["message", "callback"], arguments);
  257. if (options.callback && !$.isFunction(options.callback)) {
  258. throw new Error("alert requires callback property to be a function when provided");
  259. }
  260. /**
  261. * overrides
  262. */
  263. options.buttons.ok.callback = options.onEscape = function() {
  264. if ($.isFunction(options.callback)) {
  265. return options.callback.call(this);
  266. }
  267. return true;
  268. };
  269. return exports.dialog(options);
  270. };
  271. exports.confirm = function() {
  272. var options;
  273. options = mergeDialogOptions("confirm", ["cancel", "confirm"], ["message", "callback"], arguments);
  274. /**
  275. * overrides; undo anything the user tried to set they shouldn't have
  276. */
  277. options.buttons.cancel.callback = options.onEscape = function() {
  278. return options.callback.call(this, false);
  279. };
  280. options.buttons.confirm.callback = function() {
  281. return options.callback.call(this, true);
  282. };
  283. // confirm specific validation
  284. if (!$.isFunction(options.callback)) {
  285. throw new Error("confirm requires a callback");
  286. }
  287. return exports.dialog(options);
  288. };
  289. exports.prompt = function() {
  290. var options;
  291. var defaults;
  292. var dialog;
  293. var form;
  294. var input;
  295. var shouldShow;
  296. var inputOptions;
  297. // we have to create our form first otherwise
  298. // its value is undefined when gearing up our options
  299. // @TODO this could be solved by allowing message to
  300. // be a function instead...
  301. form = $(templates.form);
  302. // prompt defaults are more complex than others in that
  303. // users can override more defaults
  304. // @TODO I don't like that prompt has to do a lot of heavy
  305. // lifting which mergeDialogOptions can *almost* support already
  306. // just because of 'value' and 'inputType' - can we refactor?
  307. defaults = {
  308. className: "bootbox-prompt",
  309. buttons: createLabels("cancel", "confirm"),
  310. value: "",
  311. inputType: "text"
  312. };
  313. options = validateButtons(
  314. mergeArguments(defaults, arguments, ["title", "callback"]),
  315. ["cancel", "confirm"]
  316. );
  317. // capture the user's show value; we always set this to false before
  318. // spawning the dialog to give us a chance to attach some handlers to
  319. // it, but we need to make sure we respect a preference not to show it
  320. shouldShow = (options.show === undefined) ? true : options.show;
  321. /**
  322. * overrides; undo anything the user tried to set they shouldn't have
  323. */
  324. options.message = form;
  325. options.buttons.cancel.callback = options.onEscape = function() {
  326. return options.callback.call(this, null);
  327. };
  328. options.buttons.confirm.callback = function() {
  329. var value;
  330. switch (options.inputType) {
  331. case "text":
  332. case "textarea":
  333. case "email":
  334. case "select":
  335. case "date":
  336. case "time":
  337. case "number":
  338. case "password":
  339. value = input.val();
  340. break;
  341. case "checkbox":
  342. var checkedItems = input.find("input:checked");
  343. // we assume that checkboxes are always multiple,
  344. // hence we default to an empty array
  345. value = [];
  346. each(checkedItems, function(_, item) {
  347. value.push($(item).val());
  348. });
  349. break;
  350. }
  351. return options.callback.call(this, value);
  352. };
  353. options.show = false;
  354. // prompt specific validation
  355. if (!options.title) {
  356. throw new Error("prompt requires a title");
  357. }
  358. if (!$.isFunction(options.callback)) {
  359. throw new Error("prompt requires a callback");
  360. }
  361. if (!templates.inputs[options.inputType]) {
  362. throw new Error("invalid prompt type");
  363. }
  364. // create the input based on the supplied type
  365. input = $(templates.inputs[options.inputType]);
  366. switch (options.inputType) {
  367. case "text":
  368. case "textarea":
  369. case "email":
  370. case "date":
  371. case "time":
  372. case "number":
  373. case "password":
  374. input.val(options.value);
  375. break;
  376. case "select":
  377. var groups = {};
  378. inputOptions = options.inputOptions || [];
  379. if (!$.isArray(inputOptions)) {
  380. throw new Error("Please pass an array of input options");
  381. }
  382. if (!inputOptions.length) {
  383. throw new Error("prompt with select requires options");
  384. }
  385. each(inputOptions, function(_, option) {
  386. // assume the element to attach to is the input...
  387. var elem = input;
  388. if (option.value === undefined || option.text === undefined) {
  389. throw new Error("given options in wrong format");
  390. }
  391. // ... but override that element if this option sits in a group
  392. if (option.group) {
  393. // initialise group if necessary
  394. if (!groups[option.group]) {
  395. groups[option.group] = $("<optgroup/>").attr("label", option.group);
  396. }
  397. elem = groups[option.group];
  398. }
  399. elem.append("<option value='" + option.value + "'>" + option.text + "</option>");
  400. });
  401. each(groups, function(_, group) {
  402. input.append(group);
  403. });
  404. // safe to set a select's value as per a normal input
  405. input.val(options.value);
  406. break;
  407. case "checkbox":
  408. var values = $.isArray(options.value) ? options.value : [options.value];
  409. inputOptions = options.inputOptions || [];
  410. if (!inputOptions.length) {
  411. throw new Error("prompt with checkbox requires options");
  412. }
  413. if (!inputOptions[0].value || !inputOptions[0].text) {
  414. throw new Error("given options in wrong format");
  415. }
  416. // checkboxes have to nest within a containing element, so
  417. // they break the rules a bit and we end up re-assigning
  418. // our 'input' element to this container instead
  419. input = $("<div/>");
  420. each(inputOptions, function(_, option) {
  421. var checkbox = $(templates.inputs[options.inputType]);
  422. checkbox.find("input").attr("value", option.value);
  423. checkbox.find("label").append(option.text);
  424. // we've ensured values is an array so we can always iterate over it
  425. each(values, function(_, value) {
  426. if (value === option.value) {
  427. checkbox.find("input").prop("checked", true);
  428. }
  429. });
  430. input.append(checkbox);
  431. });
  432. break;
  433. }
  434. // @TODO provide an attributes option instead
  435. // and simply map that as keys: vals
  436. if (options.placeholder) {
  437. input.attr("placeholder", options.placeholder);
  438. }
  439. if (options.pattern) {
  440. input.attr("pattern", options.pattern);
  441. }
  442. if (options.maxlength) {
  443. input.attr("maxlength", options.maxlength);
  444. }
  445. // now place it in our form
  446. form.append(input);
  447. form.on("submit", function(e) {
  448. e.preventDefault();
  449. // Fix for SammyJS (or similar JS routing library) hijacking the form post.
  450. e.stopPropagation();
  451. // @TODO can we actually click *the* button object instead?
  452. // e.g. buttons.confirm.click() or similar
  453. dialog.find(".btn-primary").click();
  454. });
  455. dialog = exports.dialog(options);
  456. // clear the existing handler focusing the submit button...
  457. dialog.off("shown.bs.modal");
  458. // ...and replace it with one focusing our input, if possible
  459. dialog.on("shown.bs.modal", function() {
  460. // need the closure here since input isn't
  461. // an object otherwise
  462. input.focus();
  463. });
  464. if (shouldShow === true) {
  465. dialog.modal("show");
  466. }
  467. return dialog;
  468. };
  469. exports.dialog = function(options) {
  470. options = sanitize(options);
  471. var dialog = $(templates.dialog);
  472. var innerDialog = dialog.find(".modal-dialog");
  473. var body = dialog.find(".modal-body");
  474. var buttons = options.buttons;
  475. var buttonStr = "";
  476. var callbacks = {
  477. onEscape: options.onEscape
  478. };
  479. if ($.fn.modal === undefined) {
  480. throw new Error(
  481. "$.fn.modal is not defined; please double check you have included " +
  482. "the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ " +
  483. "for more details."
  484. );
  485. }
  486. each(buttons, function(key, button) {
  487. // @TODO I don't like this string appending to itself; bit dirty. Needs reworking
  488. // can we just build up button elements instead? slower but neater. Then button
  489. // can just become a template too
  490. buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>";
  491. callbacks[key] = button.callback;
  492. });
  493. body.find(".bootbox-body").html(options.message);
  494. if (options.animate === true) {
  495. dialog.addClass("fade");
  496. }
  497. if (options.className) {
  498. dialog.addClass(options.className);
  499. }
  500. if (options.size === "large") {
  501. innerDialog.addClass("modal-lg");
  502. } else if (options.size === "small") {
  503. innerDialog.addClass("modal-sm");
  504. }
  505. if (options.title) {
  506. body.before(templates.header);
  507. }
  508. if (options.closeButton) {
  509. var closeButton = $(templates.closeButton);
  510. if (options.title) {
  511. dialog.find(".modal-header").prepend(closeButton);
  512. } else {
  513. closeButton.css("margin-top", "-10px").prependTo(body);
  514. }
  515. }
  516. if (options.title) {
  517. dialog.find(".modal-title").html(options.title);
  518. }
  519. if (buttonStr.length) {
  520. body.after(templates.footer);
  521. dialog.find(".modal-footer").html(buttonStr);
  522. }
  523. /**
  524. * Bootstrap event listeners; used handle extra
  525. * setup & teardown required after the underlying
  526. * modal has performed certain actions
  527. */
  528. dialog.on("hidden.bs.modal", function(e) {
  529. // ensure we don't accidentally intercept hidden events triggered
  530. // by children of the current dialog. We shouldn't anymore now BS
  531. // namespaces its events; but still worth doing
  532. if (e.target === this) {
  533. dialog.remove();
  534. }
  535. });
  536. /*
  537. dialog.on("show.bs.modal", function() {
  538. // sadly this doesn't work; show is called *just* before
  539. // the backdrop is added so we'd need a setTimeout hack or
  540. // otherwise... leaving in as would be nice
  541. if (options.backdrop) {
  542. dialog.next(".modal-backdrop").addClass("bootbox-backdrop");
  543. }
  544. });
  545. */
  546. dialog.on("shown.bs.modal", function() {
  547. dialog.find(".btn-primary:first").focus();
  548. });
  549. /**
  550. * Bootbox event listeners; experimental and may not last
  551. * just an attempt to decouple some behaviours from their
  552. * respective triggers
  553. */
  554. if (options.backdrop !== "static") {
  555. // A boolean true/false according to the Bootstrap docs
  556. // should show a dialog the user can dismiss by clicking on
  557. // the background.
  558. // We always only ever pass static/false to the actual
  559. // $.modal function because with `true` we can't trap
  560. // this event (the .modal-backdrop swallows it)
  561. // However, we still want to sort of respect true
  562. // and invoke the escape mechanism instead
  563. dialog.on("click.dismiss.bs.modal", function(e) {
  564. // @NOTE: the target varies in >= 3.3.x releases since the modal backdrop
  565. // moved *inside* the outer dialog rather than *alongside* it
  566. if (dialog.children(".modal-backdrop").length) {
  567. e.currentTarget = dialog.children(".modal-backdrop").get(0);
  568. }
  569. if (e.target !== e.currentTarget) {
  570. return;
  571. }
  572. dialog.trigger("escape.close.bb");
  573. });
  574. }
  575. dialog.on("escape.close.bb", function(e) {
  576. if (callbacks.onEscape) {
  577. processCallback(e, dialog, callbacks.onEscape);
  578. }
  579. });
  580. /**
  581. * Standard jQuery event listeners; used to handle user
  582. * interaction with our dialog
  583. */
  584. dialog.on("click", ".modal-footer button", function(e) {
  585. var callbackKey = $(this).data("bb-handler");
  586. processCallback(e, dialog, callbacks[callbackKey]);
  587. });
  588. dialog.on("click", ".bootbox-close-button", function(e) {
  589. // onEscape might be falsy but that's fine; the fact is
  590. // if the user has managed to click the close button we
  591. // have to close the dialog, callback or not
  592. processCallback(e, dialog, callbacks.onEscape);
  593. });
  594. dialog.on("keyup", function(e) {
  595. if (e.which === 27) {
  596. dialog.trigger("escape.close.bb");
  597. }
  598. });
  599. // the remainder of this method simply deals with adding our
  600. // dialogent to the DOM, augmenting it with Bootstrap's modal
  601. // functionality and then giving the resulting object back
  602. // to our caller
  603. $(options.container).append(dialog);
  604. dialog.modal({
  605. backdrop: options.backdrop ? "static": false,
  606. keyboard: false,
  607. show: false
  608. });
  609. if (options.show) {
  610. dialog.modal("show");
  611. }
  612. // @TODO should we return the raw element here or should
  613. // we wrap it in an object on which we can expose some neater
  614. // methods, e.g. var d = bootbox.alert(); d.hide(); instead
  615. // of d.modal("hide");
  616. /*
  617. function BBDialog(elem) {
  618. this.elem = elem;
  619. }
  620. BBDialog.prototype = {
  621. hide: function() {
  622. return this.elem.modal("hide");
  623. },
  624. show: function() {
  625. return this.elem.modal("show");
  626. }
  627. };
  628. */
  629. return dialog;
  630. };
  631. exports.setDefaults = function() {
  632. var values = {};
  633. if (arguments.length === 2) {
  634. // allow passing of single key/value...
  635. values[arguments[0]] = arguments[1];
  636. } else {
  637. // ... and as an object too
  638. values = arguments[0];
  639. }
  640. $.extend(defaults, values);
  641. };
  642. exports.hideAll = function() {
  643. $(".bootbox").modal("hide");
  644. return exports;
  645. };
  646. /**
  647. * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are
  648. * unlikely to be required. If this gets too large it can be split out into separate JS files.
  649. */
  650. var locales = {
  651. bg_BG : {
  652. OK : "Ок",
  653. CANCEL : "Отказ",
  654. CONFIRM : "Потвърждавам"
  655. },
  656. br : {
  657. OK : "OK",
  658. CANCEL : "Cancelar",
  659. CONFIRM : "Sim"
  660. },
  661. cs : {
  662. OK : "OK",
  663. CANCEL : "Zrušit",
  664. CONFIRM : "Potvrdit"
  665. },
  666. da : {
  667. OK : "OK",
  668. CANCEL : "Annuller",
  669. CONFIRM : "Accepter"
  670. },
  671. de : {
  672. OK : "OK",
  673. CANCEL : "Abbrechen",
  674. CONFIRM : "Akzeptieren"
  675. },
  676. el : {
  677. OK : "Εντάξει",
  678. CANCEL : "Ακύρωση",
  679. CONFIRM : "Επιβεβαίωση"
  680. },
  681. en : {
  682. OK : "OK",
  683. CANCEL : "Cancel",
  684. CONFIRM : "OK"
  685. },
  686. es : {
  687. OK : "OK",
  688. CANCEL : "Cancelar",
  689. CONFIRM : "Aceptar"
  690. },
  691. et : {
  692. OK : "OK",
  693. CANCEL : "Katkesta",
  694. CONFIRM : "OK"
  695. },
  696. fa : {
  697. OK : "قبول",
  698. CANCEL : "لغو",
  699. CONFIRM : "تایید"
  700. },
  701. fi : {
  702. OK : "OK",
  703. CANCEL : "Peruuta",
  704. CONFIRM : "OK"
  705. },
  706. fr : {
  707. OK : "OK",
  708. CANCEL : "Annuler",
  709. CONFIRM : "D'accord"
  710. },
  711. he : {
  712. OK : "אישור",
  713. CANCEL : "ביטול",
  714. CONFIRM : "אישור"
  715. },
  716. hu : {
  717. OK : "OK",
  718. CANCEL : "Mégsem",
  719. CONFIRM : "Megerősít"
  720. },
  721. hr : {
  722. OK : "OK",
  723. CANCEL : "Odustani",
  724. CONFIRM : "Potvrdi"
  725. },
  726. id : {
  727. OK : "OK",
  728. CANCEL : "Batal",
  729. CONFIRM : "OK"
  730. },
  731. it : {
  732. OK : "OK",
  733. CANCEL : "Annulla",
  734. CONFIRM : "Conferma"
  735. },
  736. ja : {
  737. OK : "OK",
  738. CANCEL : "キャンセル",
  739. CONFIRM : "確認"
  740. },
  741. lt : {
  742. OK : "Gerai",
  743. CANCEL : "Atšaukti",
  744. CONFIRM : "Patvirtinti"
  745. },
  746. lv : {
  747. OK : "Labi",
  748. CANCEL : "Atcelt",
  749. CONFIRM : "Apstiprināt"
  750. },
  751. nl : {
  752. OK : "OK",
  753. CANCEL : "Annuleren",
  754. CONFIRM : "Accepteren"
  755. },
  756. no : {
  757. OK : "OK",
  758. CANCEL : "Avbryt",
  759. CONFIRM : "OK"
  760. },
  761. pl : {
  762. OK : "OK",
  763. CANCEL : "Anuluj",
  764. CONFIRM : "Potwierdź"
  765. },
  766. pt : {
  767. OK : "OK",
  768. CANCEL : "Cancelar",
  769. CONFIRM : "Confirmar"
  770. },
  771. ru : {
  772. OK : "OK",
  773. CANCEL : "Отмена",
  774. CONFIRM : "Применить"
  775. },
  776. sq : {
  777. OK : "OK",
  778. CANCEL : "Anulo",
  779. CONFIRM : "Prano"
  780. },
  781. sv : {
  782. OK : "OK",
  783. CANCEL : "Avbryt",
  784. CONFIRM : "OK"
  785. },
  786. th : {
  787. OK : "ตกลง",
  788. CANCEL : "ยกเลิก",
  789. CONFIRM : "ยืนยัน"
  790. },
  791. tr : {
  792. OK : "Tamam",
  793. CANCEL : "İptal",
  794. CONFIRM : "Onayla"
  795. },
  796. zh_CN : {
  797. OK : "OK",
  798. CANCEL : "取消",
  799. CONFIRM : "确认"
  800. },
  801. zh_TW : {
  802. OK : "OK",
  803. CANCEL : "取消",
  804. CONFIRM : "確認"
  805. }
  806. };
  807. exports.addLocale = function(name, values) {
  808. $.each(["OK", "CANCEL", "CONFIRM"], function(_, v) {
  809. if (!values[v]) {
  810. throw new Error("Please supply a translation for '" + v + "'");
  811. }
  812. });
  813. locales[name] = {
  814. OK: values.OK,
  815. CANCEL: values.CANCEL,
  816. CONFIRM: values.CONFIRM
  817. };
  818. return exports;
  819. };
  820. exports.removeLocale = function(name) {
  821. delete locales[name];
  822. return exports;
  823. };
  824. exports.setLocale = function(name) {
  825. return exports.setDefaults("locale", name);
  826. };
  827. exports.init = function(_$) {
  828. return init(_$ || $);
  829. };
  830. return exports;
  831. }));