utils.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*global jQuery, templates, escape, Jed, _ */
  2. (function (root, factory) {
  3. if (typeof define === 'function' && define.amd) {
  4. define(["jquery", "underscore", "converse-templates", "locales"], factory);
  5. } else {
  6. root.utils = factory(jQuery, _, templates);
  7. }
  8. }(this, function ($, _, templates, locales) {
  9. "use strict";
  10. var XFORM_TYPE_MAP = {
  11. 'text-private': 'password',
  12. 'text-single': 'text',
  13. 'fixed': 'label',
  14. 'boolean': 'checkbox',
  15. 'hidden': 'hidden',
  16. 'jid-multi': 'textarea',
  17. 'list-single': 'dropdown',
  18. 'list-multi': 'dropdown'
  19. };
  20. $.expr[':'].emptyVal = function(obj){
  21. return obj.value === '';
  22. };
  23. $.fn.hasScrollBar = function() {
  24. if (!$.contains(document, this.get(0))) {
  25. return false;
  26. }
  27. if(this.parent().height() < this.get(0).scrollHeight) {
  28. return true;
  29. }
  30. return false;
  31. };
  32. $.fn.addHyperlinks = function () {
  33. if (this.length > 0) {
  34. this.each(function (i, obj) {
  35. var x = $(obj).html();
  36. var list = x.match(/\b(https?:\/\/|www\.|https?:\/\/www\.)[^\s<]{2,200}\b/g );
  37. if (list) {
  38. for (i=0; i<list.length; i++) {
  39. var prot = list[i].indexOf('http://') === 0 || list[i].indexOf('https://') === 0 ? '' : 'http://';
  40. var escaped_url = encodeURI(decodeURI(list[i])).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
  41. x = x.replace(list[i], "<a target='_blank' href='" + prot + escaped_url + "'>"+ list[i] + "</a>" );
  42. }
  43. }
  44. $(obj).html(x);
  45. });
  46. }
  47. return this;
  48. };
  49. $.fn.addEmoticons = function (allowed) {
  50. if (allowed) {
  51. if (this.length > 0) {
  52. this.each(function (i, obj) {
  53. var text = $(obj).html();
  54. text = text.replace(/&gt;:\)/g, '<span class="emoticon icon-evil"></span>');
  55. text = text.replace(/:\)/g, '<span class="emoticon icon-smiley"></span>');
  56. text = text.replace(/:\-\)/g, '<span class="emoticon icon-smiley"></span>');
  57. text = text.replace(/;\)/g, '<span class="emoticon icon-wink"></span>');
  58. text = text.replace(/;\-\)/g, '<span class="emoticon icon-wink"></span>');
  59. text = text.replace(/:D/g, '<span class="emoticon icon-grin"></span>');
  60. text = text.replace(/:\-D/g, '<span class="emoticon icon-grin"></span>');
  61. text = text.replace(/:P/g, '<span class="emoticon icon-tongue"></span>');
  62. text = text.replace(/:\-P/g, '<span class="emoticon icon-tongue"></span>');
  63. text = text.replace(/:p/g, '<span class="emoticon icon-tongue"></span>');
  64. text = text.replace(/:\-p/g, '<span class="emoticon icon-tongue"></span>');
  65. text = text.replace(/8\)/g, '<span class="emoticon icon-cool"></span>');
  66. text = text.replace(/:S/g, '<span class="emoticon icon-confused"></span>');
  67. text = text.replace(/:\\/g, '<span class="emoticon icon-wondering"></span>');
  68. text = text.replace(/:\/ /g, '<span class="emoticon icon-wondering"></span>');
  69. text = text.replace(/&gt;:\(/g, '<span class="emoticon icon-angry"></span>');
  70. text = text.replace(/:\(/g, '<span class="emoticon icon-sad"></span>');
  71. text = text.replace(/:\-\(/g, '<span class="emoticon icon-sad"></span>');
  72. text = text.replace(/:O/g, '<span class="emoticon icon-shocked"></span>');
  73. text = text.replace(/:\-O/g, '<span class="emoticon icon-shocked"></span>');
  74. text = text.replace(/\=\-O/g, '<span class="emoticon icon-shocked"></span>');
  75. text = text.replace(/\(\^.\^\)b/g, '<span class="emoticon icon-thumbs-up"></span>');
  76. text = text.replace(/&lt;3/g, '<span class="emoticon icon-heart"></span>');
  77. $(obj).html(text);
  78. });
  79. }
  80. }
  81. return this;
  82. };
  83. var utils = {
  84. // Translation machinery
  85. // ---------------------
  86. __: function (str) {
  87. // Translation factory
  88. if (typeof this.i18n === "undefined") {
  89. this.i18n = locales.en;
  90. }
  91. if (typeof this.i18n === "string") {
  92. this.i18n = $.parseJSON(this.i18n);
  93. }
  94. if (typeof this.jed === "undefined") {
  95. this.jed = new Jed(this.i18n);
  96. }
  97. var t = this.jed.translate(str);
  98. if (arguments.length>1) {
  99. return t.fetch.apply(t, [].slice.call(arguments,1));
  100. } else {
  101. return t.fetch();
  102. }
  103. },
  104. ___: function (str) {
  105. /* XXX: This is part of a hack to get gettext to scan strings to be
  106. * translated. Strings we cannot send to the function above because
  107. * they require variable interpolation and we don't yet have the
  108. * variables at scan time.
  109. *
  110. * See actionInfoMessages
  111. */
  112. return str;
  113. },
  114. webForm2xForm: function (field) {
  115. /* Takes an HTML DOM and turns it into an XForm field.
  116. *
  117. * Parameters:
  118. * (DOMElement) field - the field to convert
  119. */
  120. var $input = $(field), value;
  121. if ($input.is('[type=checkbox]')) {
  122. value = $input.is(':checked') && 1 || 0;
  123. } else if ($input.is('textarea')) {
  124. value = [];
  125. var lines = $input.val().split('\n');
  126. for( var vk=0; vk<lines.length; vk++) {
  127. var val = $.trim(lines[vk]);
  128. if (val === '')
  129. continue;
  130. value.push(val);
  131. }
  132. } else {
  133. value = $input.val();
  134. }
  135. return $(templates.field({
  136. name: $input.attr('name'),
  137. value: value
  138. }))[0];
  139. },
  140. xForm2webForm: function ($field, $stanza) {
  141. /* Takes a field in XMPP XForm (XEP-004: Data Forms) format
  142. * and turns it into a HTML DOM field.
  143. *
  144. * Parameters:
  145. * (XMLElement) field - the field to convert
  146. */
  147. // FIXME: take <required> into consideration
  148. var options = [], j, $options, $values, value, values;
  149. if ($field.attr('type') === 'list-single' || $field.attr('type') === 'list-multi') {
  150. values = [];
  151. $values = $field.children('value');
  152. for (j=0; j<$values.length; j++) {
  153. values.push($($values[j]).text());
  154. }
  155. $options = $field.children('option');
  156. for (j=0; j<$options.length; j++) {
  157. value = $($options[j]).find('value').text();
  158. options.push(templates.select_option({
  159. value: value,
  160. label: $($options[j]).attr('label'),
  161. selected: (values.indexOf(value) >= 0),
  162. required: $field.find('required').length
  163. }));
  164. }
  165. return templates.form_select({
  166. name: $field.attr('var'),
  167. label: $field.attr('label'),
  168. options: options.join(''),
  169. multiple: ($field.attr('type') === 'list-multi'),
  170. required: $field.find('required').length
  171. });
  172. } else if ($field.attr('type') === 'fixed') {
  173. return $('<p class="form-help">').text($field.find('value').text());
  174. } else if ($field.attr('type') === 'jid-multi') {
  175. return templates.form_textarea({
  176. name: $field.attr('var'),
  177. label: $field.attr('label') || '',
  178. value: $field.find('value').text(),
  179. required: $field.find('required').length
  180. });
  181. } else if ($field.attr('type') === 'boolean') {
  182. return templates.form_checkbox({
  183. name: $field.attr('var'),
  184. type: XFORM_TYPE_MAP[$field.attr('type')],
  185. label: $field.attr('label') || '',
  186. checked: $field.find('value').text() === "1" && 'checked="1"' || '',
  187. required: $field.find('required').length
  188. });
  189. } else if ($field.attr('type') && $field.attr('var') === 'username') {
  190. return templates.form_username({
  191. domain: ' @'+this.domain,
  192. name: $field.attr('var'),
  193. type: XFORM_TYPE_MAP[$field.attr('type')],
  194. label: $field.attr('label') || '',
  195. value: $field.find('value').text(),
  196. required: $field.find('required').length
  197. });
  198. } else if ($field.attr('type')) {
  199. return templates.form_input({
  200. name: $field.attr('var'),
  201. type: XFORM_TYPE_MAP[$field.attr('type')],
  202. label: $field.attr('label') || '',
  203. value: $field.find('value').text(),
  204. required: $field.find('required').length
  205. });
  206. } else {
  207. if ($field.attr('var') === 'ocr') { // Captcha
  208. return _.reduce(_.map($field.find('uri'),
  209. $.proxy(function (uri) {
  210. return templates.form_captcha({
  211. label: this.$field.attr('label'),
  212. name: this.$field.attr('var'),
  213. data: this.$stanza.find('data[cid="'+uri.textContent.replace(/^cid:/, '')+'"]').text(),
  214. type: uri.getAttribute('type'),
  215. required: this.$field.find('required').length
  216. });
  217. }, {'$stanza': $stanza, '$field': $field})
  218. ),
  219. function (memo, num) { return memo + num; }, ''
  220. );
  221. }
  222. }
  223. }
  224. };
  225. return utils;
  226. }));