Fix untranslatable strings in several dijits:
[working/Evergreen.git] / Open-ILS / web / js / dojo / openils / widget / HoldingCode.js
1 if (!dojo._hasResource["openils.widget.HoldingCode"]) {
2     dojo.provide("openils.widget.HoldingCode");
3     dojo.require("dijit.layout.ContentPane");
4     dojo.require("dijit.form.DropDownButton");
5     dojo.require("dijit.form.TextBox");
6     dojo.requireLocalization('openils.serial', 'serial');
7
8     /* XXX These variables and functions preceding the call to dojo.declar()
9      * all pollute the window namespace.  They're not written as methods for
10      * the openils.widget.HoldingCode "class," but they should probably move
11      * into there anyway.
12      */
13
14     var _localeStrings = dojo.i18n.getLocalization('openils.serial', 'serial');
15
16     var _needed_fields = "abcdefghijklm";
17     var _season_store = new dojo.data.ItemFileReadStore({
18         "data": {
19             "identifier": "code",
20             "label": "label",
21             "items": [
22                 {"code": 21, "label": _localeStrings.SEASON_SPRING},
23                 {"code": 22, "label": _localeStrings.SEASON_SUMMER},
24                 {"code": 23, "label": _localeStrings.SEASON_FALL},
25                 {"code": 24, "label": _localeStrings.SEASON_WINTER}
26             ]
27         }
28     }); /* XXX i18n the above seasons. Also maybe don't
29          hardcode MFHD seasons here? */
30
31
32     function _prepare_ttip_dialog(div, wizard) {
33         dojo.empty(div);
34
35         var selector = wizard.args.scap_selector;
36         var caption_and_pattern = new scap().fromStoreItem(selector.item);
37
38         /* we're going to look for subfields a-h and i-m now. There may already
39          * be JS libs available to make this easier, but for now I'm doing this
40          * the fastest way I know. */
41
42         var pattern_code;
43         try {
44             pattern_code = JSON2js(caption_and_pattern.pattern_code());
45         } catch (E) {
46             /* no-op */;
47         }
48
49         if (!dojo.isArray(pattern_code)) {
50             div.innerHTML = _localeStrings.SELECT_VALID_CAP;
51             return;
52         }
53
54         var fields = [];
55         for (var i = 0; i < pattern_code.length; i += 2) {
56             var subfield = pattern_code[i];
57             var value = pattern_code[i + 1];
58
59             if (_needed_fields.indexOf(subfield) != -1)
60                 fields.push({"subfield": subfield, "caption": value, "pattern_value": value});
61         }
62
63         if (!fields.length) {
64             div.innerHTML = _localeStrings.NO_CAP_SUBFIELDS;
65             return;
66         }
67
68         _prepare_ttip_dialog_fields(div, fields, wizard);
69     }
70
71     function _generate_dijit_for_field(field, tr) {
72         dojo.create("td", {"innerHTML": field.caption}, tr);
73
74         /* Any more special cases than this and we should switch to a dispatch
75          * table or something. */
76         var input;
77         if (field.pattern_value.match(/season/)) {
78             input = new dijit.form.FilteringSelect(
79                 {
80                     "name": field.subfield,
81                     "store": _season_store,
82                     "searchAttr": "label",
83                     "scrollOnFocus": false
84                 }, dojo.create("td", null, tr)
85             );
86         } else {
87             input = new dijit.form.TextBox(
88                 {"name": field.subfield, "scrollOnFocus": false},
89                 dojo.create("td", null, tr)
90             );
91         }
92         input.startup();
93
94         return input;
95     }
96
97     function _prepare_ttip_dialog_fields(div, fields, wizard) {
98         /* XXX TODO Don't assume these defaults for the indicators and $8, and
99          * provide reasonable control over them. */
100         var holding_code = ["4", "1", "8", "1"];
101         var inputs = [];
102
103         wizard.wizard_button.attr("disabled", true);
104         var table = dojo.create("table", {"className": "serial-holding-code"});
105         fields.forEach(
106             function(field) {
107                 var tr = dojo.create("tr", null, table);
108
109                 field.caption = field.caption.replace(/^\(?([^\)]+)\)?$/, "$1");
110                 if (field.subfield > "h") {
111                     field.caption = field.caption.slice(0,1).toUpperCase() +
112                         field.caption.slice(1);
113                 }
114
115                 var input = _generate_dijit_for_field(field, tr);
116                 wizard.preset_input_by_date(input, field.caption.toLowerCase());
117                 inputs.push({"subfield": field.subfield, "input": input});
118             }
119         );
120
121         new dijit.form.Button(
122             {
123                 "label": _localeStrings.COMPILE,
124                 "onClick": function() {
125                     inputs.forEach(
126                         function(input) {
127                             var value = input.input.attr("value");
128                             if (value === null || value === "") {
129                                 alert(_localeStrings.ERROR_BLANK_FIELDS);
130                             }
131                             holding_code.push(input.subfield);
132                             holding_code.push(value);
133                         }
134                     );
135                     wizard.code_text_box.attr("value", js2JSON(holding_code));
136                     wizard.wizard_button.attr("disabled", false);
137                     dojo.empty(div);
138                 },
139                 "scrollOnFocus": false
140             }, dojo.create(
141                 "span", null, dojo.create(
142                     "td", {"colspan": 2},
143                     dojo.create("tr", null, table)
144                 )
145             )
146         );
147         dojo.place(table, div, "only");
148     }
149
150     /* Approximate a season value given a date using the same logic as
151      * OpenILS::Utils::MFHD::Holding::chron_to_date().
152      */
153     function _loose_season(D) {
154         var m = D.getMonth() + 1;
155         var d = D.getDate();
156
157         if (
158             (m == 1 || m == 2) || (m == 12 && d >= 21) || (m == 3 && d < 20)
159         ) {
160             return 24;  /* MFHD winter */
161         } else if (
162             (m == 4 || m == 5) || (m == 3 && d >= 20) || (m == 6 && d < 21)
163         ) {
164             return 21;  /* spring */
165         } else if (
166             (m == 7 || m == 8) || (m == 6 && d >= 21) || (m == 9 && d < 22)
167         ) {
168             return 22;  /* summer */
169         } else {
170             return 23;  /* autumn */
171         }
172     }
173
174     dojo.declare(
175         "openils.widget.HoldingCode", dijit.layout.ContentPane, {
176             "constructor": function(args) {
177                 this.args = args || {};
178             },
179
180             "startup": function() {
181                 var self = this;
182                 this.inherited(arguments);
183
184                 var dialog_div = dojo.create(
185                     "div", {
186                         "style": "padding:1em;margin:0;text-align:center;"
187                     }, this.domNode
188                 );
189                 var target_div = dojo.create("div", null, this.domNode);
190                 dojo.create("br", null, this.domNode);
191
192                 this.wizard_button = new dijit.form.Button(
193                     {
194                         "label": _localeStrings.WIZARD,
195                         "onClick": function() {
196                             _prepare_ttip_dialog(target_div, self);
197                         }
198                     },
199                     dojo.create("span", null, dialog_div)
200                 );
201
202                 this.code_text_box = new dijit.form.ValidationTextBox(
203                     {}, dojo.create("div", null, this.domNode)
204                 );
205
206                 /* This by no means will fully validate plausible holding codes,
207                  * but it will perhaps help users who experiment with typing
208                  * the holding code in here freehand (a little). */
209                 this.code_text_box.validator = function(value) {
210                     try {
211                         return dojo.isArray(dojo.fromJson(value));
212                     } catch(E) {
213                         return false;
214                     }
215                 };
216
217                 this.code_text_box.startup();
218             },
219
220             "attr": function(name, value) {
221                 if (name == "value") {
222                     /* XXX can this get called before any subdijits are
223                      * built (before startup() is run)? */
224                     if (value) {
225                         this.code_text_box.attr(name, value);
226                     }
227                     return this.code_text_box.attr(name);
228                 } else {
229                     return this.inherited(arguments);
230                 }
231             },
232
233             "update_scap_selector": function(selector) {
234                 this.args.scap_selector = selector;
235                 this.attr("value", "");
236             },
237
238             "preset_input_by_date": function(input, chron_part) {
239                 try {
240                     input.attr("value", {
241                             /* NOTE: week is specifically not covered. I'm
242                              * not sure there's an acceptably standard way
243                              * to number the weeks in a year.  Do we count
244                              * from the week of January 1? Or the first week
245                              * with a day of the week matching our example
246                              * date?  Do weeks run Mon-Sun or Sun-Sat?
247                              */
248                             "year": function(d) { return d.getFullYear(); },
249                             "season": function(d) { return _loose_season(d); },
250                             "month": function(d) { return d.getMonth() + 1; },
251                             "day": function(d) { return d.getDate(); },
252                             "hour": function(d) { return d.getHours(); },
253                         }[chron_part](this.date_widget.attr("value"))
254                     );
255                 } catch (E) {
256                     ; /* Oh well; can't win them all. */
257                 }
258             },
259
260             "date_widget": null
261         }
262     );
263 }