OSDN Git Service

js: deprecate ns-util.js, use newslash-util.js
[newslash/newslash.git] / src / newslash_web / public / js / newslash.js
1 /* newslash.js */
2
3 var Newslash = function (options) {
4   options = options || {};
5   this.baseUrl = options.baseUrl || '/api/v1';
6 };
7
8 function _initNewslash() {
9   // fake Promise for old browser
10   function FakePromise(f) {
11     this.then = function(resolve, reject) {
12       f(resolve, reject);
13     };
14   }
15
16   Newslash.prototype.fail = function fail(param) {
17     return new FakePromise(function (resolve, reject) {
18       return reject(param);
19     });
20   };
21
22   Newslash.prototype.urlParse = function (url) {
23     var parser = document.createElement('a');
24     parser.href = url;
25     return parser;
26   };
27
28   /* Utility API */
29   Newslash.prototype.pathFromDate = function (year, month, day) {
30     try {
31       year = String(year);
32       month = String(month);
33       day = String(day);
34     }
35     catch (e) { return ""; }
36     if (!year || !month || !day) { return ""; }
37     var path = "/";
38     path += year.length > 2 ? year.substring(2) : year;
39     path += month.length > 1 ? ("/" + month) : ("/0" + month);
40     path += day.length > 1 ? ("/" + day) : ("/0" + day);
41     return path + "/";
42   };
43
44   /* CSRF securiry token */
45   Newslash.getCsrfToken = function getCsrfToken(resourceID) {
46     if (!resourceID) { return this.fail(); }
47     var url = "/api/v1/token?rc=" + resourceID;
48     return this.get(url);
49   };
50
51   /* base get.post API */
52   Newslash.prototype.get = function (path) {
53     var url = this.baseUrl + path;
54     return new FakePromise(function (resolve, reject) {
55       var req = new XMLHttpRequest();
56       req.open('GET', url);
57       req.responseType = "json";
58       req.onreadystatechange = function onReadyStateChange () {
59         if (req.readyState == XMLHttpRequest.DONE) {
60           // hack for IE/Edge support (req.responseType == "json" is not supported)
61           var respType = req.responseType;
62           var resp = req.response;
63
64           if (respType === "") {
65             try {
66               resp = JSON.parse(req.response);
67               respType = "json";
68             } catch(e) {
69               console.log("Newslash.post: cannot parse JSON");
70             }
71           }
72
73           // request done
74           if (req.status == 200 && respType == "json") {
75             return resolve(resp);
76           }
77
78           // request failed
79           if (respType == "json") {
80             return reject(resp);
81           }
82           return reject(req);
83         }
84         return 1;
85       };
86       req.ontimeout = function onTimeout () {
87         return reject(req);
88       };
89       req.send();
90     });
91   };
92
93   Newslash.prototype.post = function (path, data) {
94     var url = this.baseUrl + path;
95
96     return new FakePromise((resolve, reject) => {
97       _doPost(path, data, 0, resolve, reject);
98     });
99
100     function _doPost(path, data, retryCount, resolve, reject) {
101       var req = new XMLHttpRequest();
102       req.open('POST', url);
103       req.responseType = "json";
104       req.onreadystatechange = () => {
105         if (req.readyState == XMLHttpRequest.DONE) {
106           // hack for IE/Edge support (req.responseType == "json" is not supported)
107           var respType = req.responseType;
108           var resp = req.response;
109
110           if (respType === "") {
111             try {
112               resp = JSON.parse(req.response);
113               respType = "json";
114             } catch(e) {
115               console.log("Newslash.post: cannot parse JSON");
116             }
117           }
118
119           // request done
120           if (req.status == 200 && respType == "json") {
121             return resolve(resp);
122           }
123           
124           // request failed
125           if (respType == "json") {
126             if (resp && resp.reason == "invalid_csrf_token") {
127               if (retryCount >= 3) {
128                 return reject({error: 1, reason: "exceeded retry count"});
129               }
130               var newToken = resp.csrf_token;
131               if (newToken) {
132                 data.csrf_token = newToken;
133                 // retry with new token
134                 _doPost(path, data, retryCount + 1, resolve, reject);
135                 return 1;
136               }
137             }
138             return reject(resp);
139           }
140           return reject(req);
141         }
142         return 1;
143       };
144       req.ontimeout = function onTimeout () {
145         return reject(req);
146       };
147       req.setRequestHeader("Content-Type", "application/json");
148       req.send(JSON.stringify(data));
149     }
150   };
151
152   /* login API */
153   Newslash.prototype.login = function (username, password) {
154     var url = "/login";
155     var data = {nickname: username, password: password};
156     return this.post(url, data);
157   };
158
159   /* newUser API */
160   Newslash.prototype.validateNewUser = function (username, email) {
161     var url = "/newuser/validate";
162     var data = {nickname: username, email: email};
163     return this.post(url, data);
164   };
165
166   Newslash.prototype.createNewUser = function (username, email, options) {
167     options = options || {};
168     var url = "/newuser/create";
169     var data = { nickname: username,
170                  email: email,
171                  options: options,
172                };
173     return this.post(url, data);
174   };
175
176   /* user related API */
177   Newslash.prototype.updatePasswordByToken = function (username, token, password, options) {
178     options = options || {};
179     var url = "/newuser/password";
180     var data = { nickname: username,
181                  token: token,
182                  password: password,
183                  options: options,
184                };
185     return this.post(url, data);
186   };
187
188   Newslash.prototype.requestEmailChange = function (newAddress, options) {
189     options = options || {};
190     var url = "/user";
191     var data = { type: "email", address: newAddress, };
192     return this.post("/user", data);
193   };
194
195   Newslash.prototype.updatePassword = function (oldPassword, newPassword, options) {
196     options = options || {};
197     var url = "/user";
198     var data = { type: "password",
199                  current_password: oldPassword,
200                  new_password: newPassword };
201     return this.post("/user", data);
202   };
203
204   Newslash.prototype.resetPassword = function (email) {
205     var url = "/login";
206     var data = { type: "reset_password",
207                  email: email };
208     return this.post(url, data);
209   };
210
211   Newslash.prototype.getMessageSettings = function getMessageSettings () {
212     return this.get("/user?type=message_config");
213   };
214
215   Newslash.prototype.updateSettings = function updateSettings (settings) {
216     if (!settings) return this.fail();
217     var data = { type: "config", config: settings };
218     return this.post("/user", data);
219   };
220
221   Newslash.prototype.updateMessageSettings = function updateMessageSettings (items) {
222     if (!items) return this.fail();
223     var data = { type: "message", items: items };
224     return this.post("/user", data);
225   };
226
227   /* comments API */
228   Newslash.prototype.getComments = function getComments (discussionID, parentID) {
229     if (!discussionID) return this.fail();
230
231     var url = "/comment?discussion_id=" + discussionID;
232     if (parentID) {
233       url = url + "&parent_id=" + parentID;
234     }
235     return this.get(url);
236   };
237
238   Newslash.prototype.getJournal = function getJournal (journalID) {
239     if (!journalID) return this.fail();
240
241     var url = "/journal?id=" + journalID;
242     return this.get(url);
243   };
244
245   Newslash.prototype.postJournal = function createJournal (data) {
246     data.action = "post";
247     return this.post("/journal", data);
248   };
249
250   Newslash.prototype.previewJournal = function previewJournal (data) {
251     data.action = "preview";
252     return this.post("/journal", data);
253   };
254
255   /* timeline related API */
256   Newslash.prototype.getTimeline = function getTimeline (target, options) {
257     if (!target) { target = "all"; }
258     options = options || {};
259
260     var url = "/timeline?target=" + target;
261     if (options.threshold !== undefined) {
262       url = url + "&threshold=" + options.threshold;
263     }
264
265     if (options.dateRange && options.dateRange != "all") {
266       if (!/^(\d+)_([a-z]+)$/.exec(options.dateRange)) {
267         return this.fail("invalid_date_range");
268       }
269       var ret = options.dateRange.split("_");
270       var term = ret[0];
271       var range = ret[1];
272       
273       url = url + "&" + range + "=" + term;
274     }
275     
276     return this.get(url);
277   };
278
279   Newslash.prototype.vote = function vote (globjId, voteType) {
280     var url = "/tagmoderation";
281     if (voteType != "nod" && voteType != "nix") {
282       return this.fail("invalid_voteType");
283     }
284     var data = { action: "vote",
285                  params: { name: voteType,
286                            globjid: globjId, },
287                };
288     return this.post(url, data);
289   };
290
291   Newslash.prototype.cancelVote = function cancelvote (globjId, voteType) {
292     var url = "/tagmoderation";
293     if (voteType != "nod" && voteType != "nix") {
294       return this.fail("invalid_voteType");
295     }
296     var data = { action: "unset",
297                  params: { name: voteType,
298                            globjid: globjId, },
299                };
300     return this.post(url, data);
301   };
302 }
303
304 _initNewslash();
305 var newslash = new Newslash();