muzich.js 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. * Scripts de Muzi.ch
  3. * Rédigé et propriété de Sevajol Bastien (http://www.bux.fr)
  4. *
  5. */
  6. // Messages flashs
  7. var myMessages = ['info','warning','error','success']; // define the messages types
  8. function hideAllMessages()
  9. {
  10. var messagesHeights = new Array(); // this array will store height for each
  11. for (i=0; i<myMessages.length; i++)
  12. {
  13. messagesHeights[i] = $('.' + myMessages[i]).outerHeight();
  14. $('.' + myMessages[i]).css('top', -messagesHeights[i]); //move element outside viewport
  15. }
  16. }
  17. $(document).ready(function(){
  18. // Initially, hide them all
  19. hideAllMessages();
  20. $('.message').animate({top:"0"}, 500);
  21. // When message is clicked, hide it
  22. $('.message a.message-close').click(function(){
  23. $(this).parent('.message').animate({top: -$(this).outerHeight()-50}, 700);
  24. return false;
  25. });
  26. });
  27. function findKeyWithValue(arrayt, value)
  28. {
  29. for(i in arrayt)
  30. {
  31. if (arrayt[i] == value)
  32. {
  33. return i;
  34. }
  35. }
  36. return "";
  37. }
  38. function json_to_array(json_string)
  39. {
  40. if (json_string.length)
  41. {
  42. return eval("(" + json_string + ")");
  43. }
  44. return new Array();
  45. }
  46. function strpos (haystack, needle, offset) {
  47. // Finds position of first occurrence of a string within another
  48. //
  49. // version: 1109.2015
  50. // discuss at: http://phpjs.org/functions/strpos // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  51. // + improved by: Onno Marsman
  52. // + bugfixed by: Daniel Esteban
  53. // + improved by: Brett Zamir (http://brett-zamir.me)
  54. // * example 1: strpos('Kevin van Zonneveld', 'e', 5); // * returns 1: 14
  55. var i = (haystack + '').indexOf(needle, (offset || 0));
  56. return i === -1 ? false : i;
  57. }
  58. /**
  59. * Converts the given data structure to a JSON string.
  60. * Argument: arr - The data structure that must be converted to JSON
  61. * Example: var json_string = array2json(['e', {pluribus: 'unum'}]);
  62. * var json = array2json({"success":"Sweet","failure":false,"empty_array":[],"numbers":[1,2,3],"info":{"name":"Binny","site":"http:\/\/www.openjs.com\/"}});
  63. * http://www.openjs.com/scripts/data/json_encode.php
  64. */
  65. function array2json(arr) {
  66. var parts = [];
  67. var is_list = (Object.prototype.toString.apply(arr) === '[object Array]');
  68. for(var key in arr) {
  69. var value = arr[key];
  70. if(typeof value == "object") { //Custom handling for arrays
  71. if(is_list) parts.push(array2json(value)); /* :RECURSION: */
  72. else parts[key] = array2json(value); /* :RECURSION: */
  73. } else {
  74. var str = "";
  75. if(!is_list) str = '"' + key + '":';
  76. //Custom handling for multiple data types
  77. if(typeof value == "number") str += value; //Numbers
  78. else if(value === false) str += 'false'; //The booleans
  79. else if(value === true) str += 'true';
  80. else str += '"' + value + '"'; //All other things
  81. // :TODO: Is there any more datatype we should be in the lookout for? (Functions?)
  82. parts.push(str);
  83. }
  84. }
  85. var json = parts.join(",");
  86. if(is_list) return '[' + json + ']';//Return numerical JSON
  87. return '{' + json + '}';//Return associative JSON
  88. }
  89. function isInteger(s) {
  90. return (s.toString().search(/^-?[0-9]+$/) == 0);
  91. }
  92. function inArray(array, p_val) {
  93. var l = array.length;
  94. for(var i = 0; i < l; i++) {
  95. if(array[i] == p_val) {
  96. return true;
  97. }
  98. }
  99. return false;
  100. }
  101. if(typeof(String.prototype.trim) === "undefined")
  102. {
  103. String.prototype.trim = function()
  104. {
  105. return String(this).replace(/^\s+|\s+$/g, '');
  106. };
  107. }
  108. function str_replace (search, replace, subject, count) {
  109. // Replaces all occurrences of search in haystack with replace
  110. //
  111. // version: 1109.2015
  112. // discuss at: http://phpjs.org/functions/str_replace // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  113. // + improved by: Gabriel Paderni
  114. // + improved by: Philip Peterson
  115. // + improved by: Simon Willison (http://simonwillison.net)
  116. // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) // + bugfixed by: Anton Ongson
  117. // + input by: Onno Marsman
  118. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  119. // + tweaked by: Onno Marsman
  120. // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  121. // + input by: Oleg Eremeev
  122. // + improved by: Brett Zamir (http://brett-zamir.me)
  123. // + bugfixed by: Oleg Eremeev
  124. // % note 1: The count parameter must be passed as a string in order // % note 1: to find a global variable in which the result will be given
  125. // * example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
  126. // * returns 1: 'Kevin.van.Zonneveld'
  127. // * example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
  128. // * returns 2: 'hemmo, mars' var i = 0,
  129. j = 0,
  130. temp = '',
  131. repl = '',
  132. sl = 0, fl = 0,
  133. f = [].concat(search),
  134. r = [].concat(replace),
  135. s = subject,
  136. ra = Object.prototype.toString.call(r) === '[object Array]', sa = Object.prototype.toString.call(s) === '[object Array]';
  137. s = [].concat(s);
  138. if (count) {
  139. this.window[count] = 0;
  140. }
  141. for (i = 0, sl = s.length; i < sl; i++) {
  142. if (s[i] === '') {
  143. continue;
  144. }for (j = 0, fl = f.length; j < fl; j++) {
  145. temp = s[i] + '';
  146. repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
  147. s[i] = (temp).split(f[j]).join(repl);
  148. if (count && s[i] !== temp) {this.window[count] += (temp.length - s[i].length) / f[j].length;
  149. }
  150. }
  151. }
  152. return sa ? s : s[0];
  153. }
  154. $(document).ready(function(){
  155. // Bouton de personalisation du filtre
  156. // pour le moment ce ne sotn que des redirection vers des actions
  157. $('.tags_prompt input.clear, a.filter_clear_url').live("click", function(){
  158. $(location).attr('href', $('input.filter_clear_url').val());
  159. });
  160. $('.tags_prompt input.mytags').live("click", function(){
  161. $(location).attr('href', $('input.filter_mytags_url').val());
  162. });
  163. // Affichage un/des embed
  164. $('a.element_embed_open_link').live("click", function(){
  165. li = $(this).parent('td').parent('tr').parent().parent().parent('li.element');
  166. li.find('a.element_embed_close_link').show();
  167. li.find('a.element_embed_open_link_text').hide();
  168. li.find('div.element_embed').show();
  169. return false;
  170. });
  171. $('a.element_name_embed_open_link').live("click", function(){
  172. li = $(this).parent('span').parent('td').parent('tr').parent().parent().parent('li.element');
  173. li.find('a.element_embed_close_link').show();
  174. li.find('a.element_embed_open_link_text').hide();
  175. li.find('div.element_embed').show();
  176. return false;
  177. });
  178. // Fermeture du embed si demandé
  179. $('a.element_embed_close_link').live("click", function(){
  180. li = $(this).parent('td').parent('tr').parent().parent().parent('li.element');
  181. li.find('div.element_embed').hide();
  182. li.find('a.element_embed_open_link_text').show();
  183. $(this).hide();
  184. return false;
  185. });
  186. // Mise en favoris
  187. $('a.favorite_link').live("click", function(){
  188. link = $(this);
  189. $.getJSON($(this).attr('href'), function(response) {
  190. img = link.find('img');
  191. link.attr('href', response.link_new_url);
  192. img.attr('src', response.img_new_src);
  193. img.attr('title', response.img_new_title);
  194. });
  195. return false;
  196. });
  197. // Affichage du bouton Modifier et Supprimer
  198. $('ul.elements li.element').live({
  199. mouseenter:
  200. function()
  201. {
  202. $(this).find('a.element_edit_link').show();
  203. $(this).find('a.element_remove_link').show();
  204. },
  205. mouseleave:
  206. function()
  207. {
  208. if (!$(this).find('a.element_edit_link').hasClass('mustBeDisplayed'))
  209. {
  210. $(this).find('a.element_edit_link').hide();
  211. }
  212. if (!$(this).find('a.element_remove_link').hasClass('mustBeDisplayed'))
  213. {
  214. $(this).find('a.element_remove_link').hide();
  215. }
  216. }
  217. }
  218. );
  219. // Plus d'éléments
  220. last_id = null;
  221. $('a.elements_more').click(function(){
  222. link = $(this);
  223. last_element = $('ul.elements li.element:last-child');
  224. id_last = str_replace('element_', '', last_element.attr('id'));
  225. invertcolor = 0;
  226. if (last_element.hasClass('even'))
  227. {
  228. invertcolor = 1;
  229. }
  230. $('img.elements_more_loader').show();
  231. $.getJSON(link.attr('href')+'/'+id_last+'/'+invertcolor, function(response) {
  232. if (response.count)
  233. {
  234. $('ul.elements').append(response.html);
  235. $('img.elements_more_loader').hide();
  236. }
  237. if (response.end || response.count < 1)
  238. {
  239. $('img.elements_more_loader').hide();
  240. $('ul.elements').after('<div class="no_elements"><p class="no-elements">'+
  241. response.message+'</p></div>');
  242. link.hide();
  243. }
  244. });
  245. return false;
  246. });
  247. tag_box_input_value = $('ul.tagbox input[type="text"]').val();
  248. // Filtre et affichage éléments ajax
  249. $('form[name="search"] input[type="submit"]').click(function(){
  250. $('ul.elements').html('');
  251. $('div.no_elements').hide();
  252. $('img.elements_more_loader').show();
  253. });
  254. $('form[name="search"]').ajaxForm(function(response) {
  255. $('ul.elements').html(response.html);
  256. if (response.count)
  257. {
  258. $('img.elements_more_loader').hide();
  259. $('span.elements_more').show();
  260. $('a.elements_more').show();
  261. }
  262. if (response.count < 1)
  263. {
  264. $('img.elements_more_loader').hide();
  265. $('ul.elements').after('<div class="no_elements"><p class="no-elements">'+
  266. response.message+'</p></div>');
  267. $('a.elements_more').hide()
  268. ;
  269. }
  270. $('ul.tagbox input[type="text"]').val($('ul.tagbox input[type="text"]').val());
  271. });
  272. // Suppression d'un element
  273. $('a.element_remove_link').jConfirmAction({
  274. question : "Vraiment supprimer ?",
  275. yesAnswer : "Oui",
  276. cancelAnswer : "Non",
  277. onYes: function(link){
  278. li = link.parent('td').parent('tr').parent().parent().parent('li.element');
  279. li.find('img.element_loader').show();
  280. $.getJSON(link.attr('href'), function(response){
  281. if (response.status == 'success')
  282. {
  283. li.remove();
  284. }
  285. else
  286. {
  287. li.find('img.element_loader').hide();
  288. }
  289. });
  290. return false;
  291. },
  292. onOpen: function(link){
  293. li = link.parent('td').parent('tr').parent().parent().parent('li.element');
  294. li.find('a.element_edit_link').addClass('mustBeDisplayed');
  295. li.find('a.element_remove_link').addClass('mustBeDisplayed');
  296. },
  297. onClose: function(link){
  298. li = link.parent('td').parent('tr').parent().parent().parent('li.element');
  299. li.find('a.element_edit_link').removeClass('mustBeDisplayed');
  300. li.find('a.element_remove_link').removeClass('mustBeDisplayed');
  301. li.find('a.element_edit_link').hide();
  302. li.find('a.element_remove_link').hide();
  303. }
  304. });
  305. elements_edited = new Array();
  306. // Ouverture du formulaire de modification
  307. $('a.element_edit_link').live('click', function(){
  308. link = $(this);
  309. li = link.parent('td').parent('tr').parent().parent().parent('li.element');
  310. // On garde en mémoire l'élément édité en cas d'annulation
  311. elements_edited[li.attr('id')] = li.html();
  312. div_loader = li.find('div.loader');
  313. li.html(div_loader);
  314. li.find('img.element_loader').show();
  315. $.getJSON($(this).attr('href'), function(response) {
  316. // On prépare le tagBox
  317. li.html(response.html);
  318. var options = new Array();
  319. options.form_name = response.form_name;
  320. options.tag_init = response.tags;
  321. ajax_query_timestamp = null;
  322. $("#tags_prompt_list_"+response.form_name).tagBox(options);
  323. // On rend ce formulaire ajaxFormable
  324. $('form[name="'+response.form_name+'"] input[type="submit"]').live('click', function(){
  325. li.prepend(div_loader);
  326. li.find('img.element_loader').show();
  327. });
  328. $('form[name="'+response.form_name+'"]').ajaxForm(function(response){
  329. if (response.status == 'success')
  330. {
  331. li.html(response.html);
  332. delete(elements_edited[li.attr('id')]);
  333. }
  334. else if (response.status == 'error')
  335. {
  336. li.find('img.element_loader').hide();
  337. li.find('ul.error_list').remove();
  338. ul_errors = $('<ul>').addClass('error_list');
  339. for (i in response.errors)
  340. {
  341. ul_errors.append($('<li>').append(response.errors[i]));
  342. }
  343. li.prepend(ul_errors);
  344. }
  345. });
  346. });
  347. return false;
  348. });
  349. // Annulation d'un formulaire de modification d'élément
  350. $('form.edit_element input.cancel_edit').live('click', function(){
  351. var li = $(this).parent('form').parent('li');
  352. li.html(elements_edited[li.attr('id')]);
  353. delete(elements_edited[li.attr('id')]);
  354. });
  355. ////////////////// TAG PROMPT ///////////////
  356. ajax_query_timestamp = null;
  357. tag_text_help = $('input.tag_text_help').val();
  358. // Les deux clicks ci-dessous permettent de faire disparaitre
  359. // la div de tags lorsque l'on clique ailleurs
  360. $('html').click(function() {
  361. if ($("div.search_tag_list").is(':visible'))
  362. {
  363. $("div.search_tag_list").hide();
  364. }
  365. });
  366. $("div.search_tag_list").live('click', function(event){
  367. event.stopPropagation();
  368. });
  369. function autocomplete_tag(input, form_name)
  370. {
  371. // Il doit y avoir au moin un caractère
  372. if (input.val().length > 0)
  373. {
  374. // on met en variable l'input
  375. inputTag = input;
  376. // On récupére la div de tags
  377. divtags = $("#search_tag_"+form_name);
  378. // Si la fenêtre de tags est caché
  379. if (!divtags.is(':visible'))
  380. {
  381. // On la replace
  382. position = input.position();
  383. divtags.css('left', Math.round(position.left) + 5);
  384. divtags.css('top', Math.round(position.top) + 28);
  385. // Et on l'affiche
  386. divtags.show();
  387. }
  388. // On affiche le loader
  389. $('#tag_loader_'+form_name).show();
  390. // On cache la liste de tags
  391. search_tag_list = divtags.find('ul.search_tag_list');
  392. // On supprime les anciens li
  393. search_tag_list.find('li').remove();
  394. search_tag_list.hide();
  395. // Et on affiche une info
  396. span_info = divtags.find('span.info');
  397. span_info.show();
  398. span_info.text("Recherche des tags correspondants à \""+input.val()+"\" ...");
  399. // C'est en fonction du nb de resultats qu'il sera affiché
  400. divtags.find('a.more').hide();
  401. // On récupère le timestamp pour reconnaitre la dernière requête effectué
  402. ajax_query_timestamp = new Date().getTime();
  403. // Récupération des tags correspondants
  404. $.getJSON('/app_dev.php/fr/search/tag/'+input.val()+'/'+ajax_query_timestamp, function(data) {
  405. // Ce contrôle permet de ne pas continuer si une requete
  406. // ajax a été faite depuis.
  407. if (data.timestamp == ajax_query_timestamp)
  408. {
  409. status = data.status;
  410. tags = data.data;
  411. // Si on spécifie une erreur
  412. if (status == 'error')
  413. {
  414. // On l'affiche a l'utilisateur
  415. span_info.text(data.error);
  416. }
  417. // Si c'est un succés
  418. else if (status == 'success')
  419. {
  420. if (tags.length > 0)
  421. {
  422. more = false;
  423. // Pour chaque tags retournés
  424. for (i in tags)
  425. {
  426. var tag_name = tags[i]['name'];
  427. var tag_id = tags[i]['id'];
  428. // On construit un li
  429. var sstr = $.trim(input.val());
  430. var re = new RegExp(sstr, "i") ;
  431. var t_string = tag_name.replace(re,"<strong>" + sstr + "</strong>");
  432. li_tag =
  433. $('<li>').append(
  434. $('<a>').attr('href','#'+tag_id+'#'+tag_name)
  435. // qui réagit quand on clique dessus
  436. .click(function(e){
  437. // On récupère le nom du tag
  438. name = $(this).attr('href').substr(1,$(this).attr('href').length);
  439. name = name.substr(strpos(name, '#')+1, name.length);
  440. id = $(this).attr('href').substr(1,$(this).attr('href').length);
  441. id = str_replace(name, '', id);
  442. id = str_replace('#', '', id);
  443. $('input#tags_selected_tag_'+form_name).val(id);
  444. inputTag.val(name);
  445. // Et on execute l'évènement selectTag de l'input
  446. inputTag.trigger("selectTag");
  447. // On cache la liste puisque le choix vient d'être fait
  448. divtags.hide();
  449. inputTag.val(tag_text_help);
  450. return false;
  451. })
  452. .append(t_string)
  453. );
  454. // Si on depasse les 30 tags
  455. if (i > 30)
  456. {
  457. more = true;
  458. // On le cache
  459. li_tag.hide();
  460. }
  461. // On ajout ce li a la liste
  462. search_tag_list.append(li_tag);
  463. }
  464. if (more)
  465. {
  466. divtags.find('a.more').show();
  467. }
  468. // On cache l'info
  469. span_info.hide();
  470. // Et on affiche la liste
  471. search_tag_list.show();
  472. }
  473. else
  474. {
  475. span_info.text("Aucun tag de trouvé pour \""+inputTag.val()+"\"");
  476. }
  477. }
  478. // On cache le loader
  479. $('#tag_loader_'+form_name).hide();
  480. }
  481. });
  482. }
  483. }
  484. last_keypress = 0;
  485. function check_timelaps_and_search(input, form_name, time_id, timed, info)
  486. {
  487. if (!timed)
  488. {
  489. // C'est une nouvelle touche (pas redirigé) on lui donne un id
  490. // et on met a jour l'id de la dernière pressé
  491. last_keypress = new Date().getTime();
  492. var this_time_id = last_keypress;
  493. }
  494. else
  495. {
  496. // Si elle a été redirigé, on met son id dans cette variable
  497. var this_time_id = time_id;
  498. }
  499. // C'est une touche redirigé dans le temps qui a été suivit d'une autre touche
  500. if (time_id != last_keypress && timed)
  501. {
  502. // elle disparait
  503. }
  504. else
  505. {
  506. //
  507. if ((new Date().getTime() - last_keypress) < 600 || timed == false)
  508. {
  509. // Si elle vient d'être tapé (timed == false) elle doit attendre (au cas ou une autre touche soit tapé)
  510. // Si c'est une redirigé qui n'a pas été remplacé par une nouvelle lettre
  511. // elle doit attendre au cas ou soit pressé.
  512. setTimeout(function(){check_timelaps_and_search(input, form_name, this_time_id, true, info)}, 700);
  513. }
  514. else
  515. {
  516. // il n'y a plus a attendre, on envoie la demande de tag.
  517. autocomplete_tag(input, form_name);
  518. }
  519. }
  520. }
  521. // Autocompletion de tags
  522. $("div.tags_prompt ul.tagbox li.input input").live('keypress', function(e){
  523. var form_name = $(this).parent('li').parent('ul.tagbox')
  524. .parent('div.tags_prompt').parent('form').attr('name')
  525. ;
  526. var code = (e.keyCode ? e.keyCode : e.which);
  527. if ((e.which !== 0 && e.charCode !== 0) || (code == 8 || code == 46))
  528. {
  529. check_timelaps_and_search($(this), form_name, new Date().getTime(), false, $(this).val());
  530. }
  531. });
  532. // Un click sur ce lien affiche tout les tags cachés de la liste
  533. $('div.search_tag_list a.more').live('click', function(){
  534. jQuery.each( $(this).parent('div').find('ul.search_tag_list li') , function(){
  535. $(this).show();
  536. });
  537. return false;
  538. });
  539. $('ul.tagbox li.input input[type="text"]').val(tag_text_help);
  540. $('ul.tagbox li.input input[type="text"]').formDefaults();
  541. ////////////////// FIN TAG PROMPT ///////////////
  542. // Suppression d'un element
  543. $('a.group_remove_link').jConfirmAction({
  544. question : "Supprimer ce groupe ?",
  545. yesAnswer : "Oui",
  546. cancelAnswer : "Non",
  547. onYes: function(link){
  548. window.location = link.attr('href');
  549. return false;
  550. },
  551. onOpen: function(){},
  552. onClose: function(){}
  553. });
  554. // Selection Réseau global / Mon réseau
  555. $('div.select_network a').live('click', function(){
  556. divSelect = $(this).parent('div');
  557. if ($(this).hasClass('all_network'))
  558. {
  559. divSelect.find('a.all_network').addClass('active');
  560. divSelect.find('a.my_network').removeClass('active');
  561. divSelect.find('select').val('network_public');
  562. }
  563. else
  564. {
  565. divSelect.find('a.my_network').addClass('active');
  566. divSelect.find('a.all_network').removeClass('active');
  567. divSelect.find('select').val('network_personal');
  568. }
  569. });
  570. });