jquery.couchapp.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  2. // use this file except in compliance with the License. You may obtain a copy
  3. // of the License at
  4. //
  5. // http://www.apache.org/licenses/LICENSE-2.0
  6. //
  7. // Unless required by applicable law or agreed to in writing, software
  8. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. // License for the specific language governing permissions and limitations under
  11. // the License.
  12. // Usage: The passed in function is called when the page is ready.
  13. // CouchApp passes in the app object, which takes care of linking to
  14. // the proper database, and provides access to the CouchApp helpers.
  15. // $.CouchApp(function(app) {
  16. // app.db.view(...)
  17. // ...
  18. // });
  19. (function($) {
  20. function f(n) { // Format integers to have at least two digits.
  21. return n < 10 ? '0' + n : n;
  22. }
  23. Date.prototype.toJSON = function() {
  24. return this.getUTCFullYear() + '/' +
  25. f(this.getUTCMonth() + 1) + '/' +
  26. f(this.getUTCDate()) + ' ' +
  27. f(this.getUTCHours()) + ':' +
  28. f(this.getUTCMinutes()) + ':' +
  29. f(this.getUTCSeconds()) + ' +0000';
  30. };
  31. function Design(db, name) {
  32. this.view = function(view, opts) {
  33. db.view(name+'/'+view, opts);
  34. };
  35. };
  36. var login;
  37. function init(app) {
  38. $(function() {
  39. var dbname = document.location.href.split('/')[3];
  40. var dname = unescape(document.location.href).split('/')[5];
  41. var db = $.couch.db(dbname);
  42. var design = new Design(db, dname);
  43. // docForm applies CouchDB behavior to HTML forms.
  44. function docForm(formSelector, opts) {
  45. var localFormDoc = {};
  46. opts = opts || {};
  47. opts.fields = opts.fields || [];
  48. // turn the form into deep json
  49. // field names like 'author-email' get turned into json like
  50. // {"author":{"email":"quentin@example.com"}}
  51. // Note: Fields not found in form are ignored.
  52. function formToDeepJSON(form, fields, doc) {
  53. var form = $(form);
  54. fields.forEach(function(field) {
  55. var elem = form.find("[name="+field+"]");
  56. if (!elem) return;
  57. var parts = field.split('-');
  58. var frontObj = doc, frontName = parts.shift();
  59. while (parts.length > 0) {
  60. frontObj[frontName] = frontObj[frontName] || {}
  61. frontObj = frontObj[frontName];
  62. frontName = parts.shift();
  63. }
  64. frontObj[frontName] = elem.val();
  65. });
  66. };
  67. // Apply the behavior
  68. $(formSelector).submit(function(e) {
  69. e.preventDefault();
  70. // formToDeepJSON acts on localFormDoc by reference
  71. formToDeepJSON(this, opts.fields, localFormDoc);
  72. if (opts.beforeSave) opts.beforeSave(localFormDoc);
  73. db.saveDoc(localFormDoc, {
  74. success : function(resp) {
  75. if (opts.success) opts.success(resp, localFormDoc);
  76. }
  77. })
  78. return false;
  79. });
  80. // populate form from an existing doc
  81. function docToForm(doc) {
  82. var form = $(formSelector);
  83. // fills in forms
  84. opts.fields.forEach(function(field) {
  85. var parts = field.split('-');
  86. var frontObj = doc, frontName = parts.shift();
  87. while (frontObj && parts.length > 0) {
  88. frontObj = frontObj[frontName];
  89. frontName = parts.shift();
  90. }
  91. if (frontObj && frontObj[frontName])
  92. form.find("[name="+field+"]").val(frontObj[frontName]);
  93. });
  94. };
  95. if (opts.id) {
  96. db.openDoc(opts.id, {
  97. success: function(doc) {
  98. if (opts.onLoad) opts.onLoad(doc);
  99. localFormDoc = doc;
  100. docToForm(doc);
  101. }});
  102. } else if (opts.template) {
  103. if (opts.onLoad) opts.onLoad(opts.template);
  104. localFormDoc = opts.template;
  105. docToForm(localFormDoc);
  106. }
  107. var instance = {
  108. deleteDoc : function(opts) {
  109. opts = opts || {};
  110. if (confirm("Really delete this document?")) {
  111. db.removeDoc(localFormDoc, opts);
  112. }
  113. },
  114. localDoc : function() {
  115. formToDeepJSON(formSelector, opts.fields, localFormDoc);
  116. return localFormDoc;
  117. }
  118. }
  119. return instance;
  120. }
  121. function prettyDate(time){
  122. var date = new Date(time),
  123. diff = (((new Date()).getTime() - date.getTime()) / 1000),
  124. day_diff = Math.floor(diff / 86400);
  125. return day_diff < 1 && (
  126. diff < 60 && "just now" ||
  127. diff < 120 && "1 minute ago" ||
  128. diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
  129. diff < 7200 && "1 hour ago" ||
  130. diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
  131. day_diff == 1 && "yesterday" ||
  132. day_diff < 21 && day_diff + " days ago" ||
  133. day_diff < 45 && Math.ceil( day_diff / 7 ) + " weeks ago" ||
  134. day_diff < 730 && Math.ceil( day_diff / 31 ) + " months ago" ||
  135. Math.ceil( day_diff / 365 ) + " years ago";
  136. };
  137. app({
  138. showPath : function(funcname, docid) {
  139. // I wish this was shared with path.js...
  140. return '/'+[dbname, '_design', dname, '_show', funcname, docid].join('/')
  141. },
  142. listPath : function(funcname, viewname) {
  143. return '/'+[dbname, '_design', dname, '_list', funcname, viewname].join('/')
  144. },
  145. slugifyString : function(string) {
  146. return string.replace(/\W/g,'-').
  147. replace(/\-*$/,'').replace(/^\-*/,'').
  148. replace(/\-{2,}/,'-');
  149. },
  150. attemptLogin : function(win, fail) {
  151. // depends on nasty hack in blog validation function
  152. db.saveDoc({"author":"_self"}, { error: function(s, e, r) {
  153. var namep = r.split(':');
  154. if (namep[0] == '_self') {
  155. login = namep.pop();
  156. $.cookies.set("login", login, '/'+dbname)
  157. win && win(login);
  158. } else {
  159. $.cookies.set("login", "", '/'+dbname)
  160. fail && fail(s, e, r);
  161. }
  162. }});
  163. },
  164. loggedInNow : function(loggedIn, loggedOut) {
  165. login = login || $.cookies.get("login");
  166. if (login) {
  167. loggedIn && loggedIn(login);
  168. } else {
  169. loggedOut && loggedOut();
  170. }
  171. },
  172. db : db,
  173. design : design,
  174. view : design.view,
  175. docForm : docForm,
  176. prettyDate : prettyDate
  177. });
  178. });
  179. };
  180. $.CouchApp = $.CouchApp || init;
  181. })(jQuery);