Advertisement
Guest User

Untitled

a guest
Aug 26th, 2016
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.81 KB | None | 0 0
  1. // WIP
  2.  
  3. ///
  4. // page base
  5. ///
  6.  
  7. var Page = function() {
  8. $('#menu .' + this.id).addClass('selected');
  9. };
  10.  
  11. Page.prototype.init = function() {
  12. // clear query button
  13. $('#text')
  14. .wrap('<div id="text-wrapper"></div>')
  15. .addClass('with-clear-button')
  16. .keyup(function(event) {
  17. var $this = $(this);
  18. if ($this.val().trim() === '') {
  19. $('#clear-button').hide();
  20. } else {
  21. $('#clear-button').show();
  22. }
  23. if (event.which === 27) { // esc
  24. $('#clear-button').click();
  25. }
  26. });
  27. $('#text-wrapper').append(
  28. $('<div id="clear-button" title="Clear" style="display:none"></div>')
  29. .mousedown(function() {
  30. $(this).addClass('active');
  31. })
  32. .mouseup(function() {
  33. $(this).removeClass('active');
  34. })
  35. .click(function() {
  36. $('#text').val('').keyup();
  37. $('#search').click();
  38. })
  39. );
  40. };
  41.  
  42. Page.prototype.searchQuery = function(loc) {
  43. // load search query from hash (legacy) or query string
  44. loc = loc || window.location;
  45. if (loc.hash.startsWith('#search/')) {
  46. return loc.hash.substring(8).trim();
  47. } else if (loc.search.startsWith('?search/')) {
  48. return loc.search.substring(8).trim();
  49. } else {
  50. return '';
  51. }
  52. };
  53.  
  54. Page.prototype.showThrobber = function() {
  55. $('#throbber').css('visibility', 'visible');
  56. };
  57.  
  58. Page.prototype.hideThrobber = function() {
  59. $('#throbber').css('visibility', 'hidden');
  60. };
  61.  
  62. Page.prototype.linkifyCard = function($parent) {
  63. // change card links to js handlers
  64. var page = this;
  65. $parent.find('.manager a:not(.org-chart)').click(function(event) {
  66. event.preventDefault();
  67. $('#text').val(page.searchQuery(this)).keyup();
  68. $('#search').click();
  69. });
  70. };
  71.  
  72. Page.prototype.noResults = function($parent) {
  73. // display "no results" message in parent
  74. $parent.html(
  75. $('.no-results')
  76. .clone()
  77. .show()
  78. );
  79. };
  80.  
  81. //
  82. // cards
  83. //
  84.  
  85. function CardPage() {
  86. this.id = this.id || 'card';
  87. Page.call(this);
  88. if (!this.searchQuery()) {
  89. $('#phonebook-search').addClass('large');
  90. }
  91. }
  92. CardPage.prototype = Object.create(Page.prototype);
  93. CardPage.prototype.constructor = CardPage;
  94.  
  95. CardPage.prototype.init = function() {
  96. Page.prototype.init.call(this);
  97. var query = this.searchQuery();
  98. if (query) {
  99. $('#text').val(query).keyup();
  100. $('#search').click();
  101. } else {
  102. $('#text').focus().select();
  103. }
  104. };
  105.  
  106. CardPage.prototype.search = function(query) {
  107. var page = this;
  108. return new Promise(function(resolve, reject) {
  109. var url = './search.php?format=html&query=' + encodeURIComponent(query);
  110. $('#results').load(url, function() {
  111. if (!$('#results').text()) {
  112. page.noResults($('#results'));
  113. } else {
  114. page.linkifyCard($('#results'));
  115. }
  116. resolve();
  117. });
  118. });
  119. };
  120.  
  121. CardPage.prototype.clear = function() {
  122. $('#results').empty();
  123. };
  124.  
  125. //
  126. // faces
  127. //
  128.  
  129. function WallPage() {
  130. this.id = this.id || 'wall';
  131. CardPage.call(this);
  132. }
  133. WallPage.prototype = Object.create(CardPage.prototype);
  134. WallPage.prototype.constructor = WallPage;
  135.  
  136. WallPage.prototype.init = function() {
  137. CardPage.prototype.init.call(this);
  138. $('#overlay')
  139. .click(function() {
  140. $('body').removeClass('lightbox');
  141. });
  142. };
  143.  
  144. WallPage.prototype.search = function(query) {
  145. var page = this;
  146. return new Promise(function(resolve, reject) {
  147. var url = 'search.php?format=json&query=' + encodeURIComponent(query);
  148. $.getJSON(url, function(data) {
  149. var $results = $('#results');
  150. if (data.length) {
  151. $results.empty();
  152. $.each(data, function() {
  153. $results.append(
  154. $('<div class="photo-frame"></div>')
  155. .data('mail', this.mail)
  156. .append(
  157. $('<span></span>').text(this.cn)
  158. )
  159. .append(
  160. $('<img class="wall-photo">')
  161. .attr('src', 'pic.php?type=thumb&mail=' + encodeURIComponent(this.mail))
  162. )
  163. .click(page, page.showCard)
  164. );
  165. });
  166. } else {
  167. page.noResults($results);
  168. }
  169. resolve();
  170. });
  171. });
  172. };
  173.  
  174. WallPage.prototype.showCard = function(event) {
  175. var page = event.data;
  176. var mail = $(this).data('mail');
  177. page.showThrobber();
  178. $.ajax({
  179. url: 'search.php?format=html&query=' + encodeURIComponent(mail),
  180. success: function(html) {
  181. $('body').addClass('lightbox');
  182. $('#overlay').html(html);
  183. $('#overlay .header')
  184. .append(
  185. $('<div class="close-button" title="Close">')
  186. .click(function() {
  187. $('#overlay').click();
  188. })
  189. );
  190. },
  191. complete: function() {
  192. page.hideThrobber();
  193. }
  194. });
  195. };
  196.  
  197. //
  198. // tree
  199. //
  200.  
  201. function TreePage() {
  202. this.id = this.id || 'tree';
  203. Page.call(this);
  204. }
  205. TreePage.prototype = Object.create(Page.prototype);
  206. TreePage.prototype.constructor = CardPage;
  207.  
  208. TreePage.prototype.init = function() {
  209. Page.prototype.init.call(this);
  210. var page = this;
  211.  
  212. var query = this.searchQuery();
  213. if (query) {
  214. $('#text').val(query).keyup();
  215. $('#search').click();
  216. } else {
  217. $('#text').focus().select();
  218. }
  219.  
  220. // clicking on a name -> show card
  221. $('.hr-link').click(function(event) {
  222. event.preventDefault();
  223. event.stopPropagation();
  224. var mail = $(this).attr('href').substring(8);
  225. page.showCard(mail);
  226. });
  227.  
  228. // collapse / expand
  229. $('#orgchart li, #orphans li').click(function(event) {
  230. event.preventDefault();
  231. var $this = $(this);
  232. if ($this.hasClass('expanded')) {
  233. page.collapseNode($this);
  234. } else {
  235. page.expandNode($this);
  236. }
  237. });
  238.  
  239. // stick visible card when scrolling
  240. $(window).scroll(function() {
  241. var $card = $('#person div.vcard');
  242. if ($card.length !== 1) {
  243. return;
  244. }
  245. if ($(window).scrollTop() > $('#orgchart').offset().top) {
  246. $card.addClass('snap-to-top');
  247. } else {
  248. $card.removeClass('snap-to-top');
  249. }
  250. });
  251. };
  252.  
  253. TreePage.prototype.childNodes = function($parent) {
  254. // children are in an adjacent <ul>
  255. return $('#' + $parent.attr('id') + ' + ul');
  256. };
  257.  
  258. TreePage.prototype.collapseNode = function($parent) {
  259. if ($parent.hasClass('collapsed')) {
  260. return;
  261. }
  262. var $children = this.childNodes($parent);
  263. if (!$children.length) {
  264. return;
  265. }
  266. $parent.removeClass('expanded').addClass('collapsed');
  267. $children.hide();
  268. };
  269.  
  270. TreePage.prototype.expandNode = function($parent) {
  271. if ($parent.hasClass('expanded')) {
  272. return;
  273. }
  274. var $children = this.childNodes($parent);
  275. if (!$children.length) {
  276. return;
  277. }
  278. $parent.removeClass('collapsed').addClass('expanded');
  279. $children.show();
  280. };
  281.  
  282. TreePage.prototype.expandAllNodes = function() {
  283. var page = this;
  284. $('#orgchart li.collapsed, #orphans li.collapsed').each(function() {
  285. page.expandNode($(this));
  286. });
  287. };
  288.  
  289. TreePage.prototype.mailToID = function(mail) {
  290. return '#' + mail.replace('@', '-at-').replace('.', '_');
  291. };
  292.  
  293. TreePage.prototype.search = function(query) {
  294. var page = this;
  295. return new Promise(function(resolve, reject) {
  296. var url = 'search.php?format=json&query=' + encodeURIComponent(query);
  297. $('#orgchart').removeClass('filter-view');
  298. $('#person').empty();
  299. $.getJSON(url, function(results) {
  300. // no results
  301. if (results.length === 0) {
  302. page.noResults($('#person'));
  303. resolve();
  304. return;
  305. }
  306.  
  307. // highlight matches
  308. $('#orgchart').addClass('filter-view');
  309. $.each(results, function() {
  310. var id = page.mailToID(this.mail);
  311. $(id).addClass('highlighted');
  312. });
  313.  
  314. // collapse
  315. page.expandAllNodes();
  316. $('#orgchart li:not(.leaf)').each(function() {
  317. var $parent = $(this);
  318. var $children = page.childNodes($parent);
  319. if ($children.find('.highlighted').length === 0) {
  320. page.collapseNode($parent);
  321. }
  322. });
  323.  
  324. // expand matches
  325. var $person = $('#orgchart li.highlighted');
  326. $person.each(function() {
  327. page.expandNode($(this));
  328. });
  329.  
  330. // and bring into view
  331. $('html').animate({ scrollTop: $person.first().offset().top - 2 });
  332. resolve();
  333. });
  334. });
  335. };
  336.  
  337. TreePage.prototype.showCard = function(mail) {
  338. var page = this;
  339. page.clear();
  340. window.history.pushState({}, '',
  341. window.location.pathname + '?search/' + mail);
  342.  
  343. var $person = $(page.mailToID(mail));
  344. $person.addClass('selected');
  345. $('html').animate({ scrollTop: $person.offset().top - 2 });
  346. $('#text').val(mail).keyup();
  347.  
  348. page.showThrobber();
  349. $.ajax({
  350. url: 'search.php?format=html&exact_search=true&query=' + encodeURIComponent(mail),
  351. success: function(html) {
  352. $('#person').html(html);
  353. page.linkifyCard($('#person'));
  354. $(window).scroll();
  355. },
  356. complete: function() {
  357. page.hideThrobber();
  358. }
  359. });
  360. };
  361.  
  362. TreePage.prototype.clear = function() {
  363. function reset(id) {
  364. $(id).removeClass('filter-view');
  365. $(id + ' li.selected').removeClass('selected');
  366. $(id + ' li.highlighted').removeClass('highlighted');
  367. }
  368. $('#person').empty();
  369. reset('#orgchart');
  370. reset('#orphans');
  371. this.expandAllNodes();
  372. this.collapseNode($('#managerless'));
  373. };
  374.  
  375. TreePage.prototype.linkifyCard = function($parent) {
  376. var page = this;
  377. // change card links to js handlers
  378. $parent.find('.manager a').click(function(event) {
  379. event.preventDefault();
  380. page.showCard(page.searchQuery(this));
  381. });
  382. };
  383.  
  384. //
  385. // edit
  386. //
  387.  
  388. function EditPage() {
  389. this.id = this.id || 'edit';
  390. Page.call(this);
  391. }
  392. EditPage.prototype = Object.create(Page.prototype);
  393. EditPage.prototype.constructor = Page;
  394.  
  395. EditPage.prototype.init = function() {
  396. Page.prototype.init.call(this);
  397.  
  398. $('#email-alias-add')
  399. .data({ name: 'emailAlias[]', title: 'e-mail' })
  400. .addClass('add-link');
  401. $('#phone-number-add')
  402. .data({ name: 'mobile[]', title: 'number' })
  403. .addClass('add-link');
  404. $('#im-add')
  405. .data({ name: 'im[]', title: 'account' })
  406. .addClass('add-link');
  407. $('#office-add')
  408. .data({ name: 'office_city[]', title: 'office' })
  409. .addClass('add-office');
  410.  
  411. $('.add-link').click(this, this.addValue);
  412. $('.remove-link').click(this.removeValue);
  413. };
  414.  
  415. EditPage.prototype.clear = function() {};
  416.  
  417. EditPage.prototype.search = function(query) {
  418. window.location = window.location.pathname.replace('edit.php', '?search/' + query);
  419. return new Promise(function() {});
  420. };
  421.  
  422. EditPage.prototype.addValue = function(event) {
  423. event.preventDefault();
  424. var $this = $(this);
  425. var page = event.data;
  426. $('<div/>')
  427. .append(
  428. $('<input type="text">')
  429. .attr('name', $this.data('name'))
  430. )
  431. .append(
  432. $('<a href="#" class="remove-link">')
  433. .attr('title', 'Remove ' + $this.data('title'))
  434. .click(page.removeValue)
  435. )
  436. .insertBefore($this)
  437. .find('input')
  438. .focus();
  439. };
  440.  
  441. EditPage.prototype.removeValue = function(event) {
  442. event.preventDefault();
  443. $(this)
  444. .parent('div')
  445. .remove();
  446. };
  447.  
  448. // startup
  449.  
  450. var pb_page;
  451. var pageID = $('body').data('page');
  452. if (pageID === 'wall') {
  453. pb_page = new WallPage();
  454. } else if (pageID === 'tree') {
  455. pb_page = new TreePage();
  456. } else if (pageID === 'edit') {
  457. pb_page = new EditPage();
  458. } else {
  459. pb_page = new CardPage();
  460. }
  461.  
  462. $(function() {
  463. $('#search').click(function(event) {
  464. event.preventDefault();
  465.  
  466. var $text = $('#text');
  467. var filter = $text.val().trim();
  468. var queryString = filter === '' ? '' : '?search/' + filter;
  469.  
  470. // update url
  471. window.history.pushState({}, '',
  472. window.location.pathname + queryString);
  473.  
  474. // update other page links to include search filter
  475. $('#menu li a:not(.edit)').each(function() {
  476. this.href = this.pathname + queryString;
  477. });
  478.  
  479. // don't rerun identical queries
  480. if (filter === $text.data('last')) {
  481. return;
  482. }
  483. $text.data('last', filter);
  484.  
  485. pb_page.clear();
  486.  
  487. // run search
  488. if (filter === '') {
  489. $('#text').focus().select();
  490. } else {
  491. $('#phonebook-search').removeClass('large');
  492. pb_page.showThrobber();
  493. pb_page.search(filter).then(pb_page.hideThrobber);
  494. }
  495. });
  496.  
  497. pb_page.init();
  498. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement