skill_tree.tpl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. <style>
  2. /* just because */
  3. body {
  4. /* fallback */
  5. background-color: #eee;
  6. background-image: url(images/radial_bg.png);
  7. background-position: center center;
  8. background-repeat: no-repeat;
  9. /* Safari 4-5, Chrome 1-9 */ /* Can't specify a percentage size? Laaaaaame. */
  10. background: -webkit-gradient(radial, center center, 0, center center, 460, from(#eee), to(#666));
  11. /* Safari 5.1+, Chrome 10+ */
  12. background: -webkit-radial-gradient(circle, #eee, #666);
  13. /* Firefox 3.6+ */
  14. background: -moz-radial-gradient(circle, #eee, #666);
  15. /* IE 10 */
  16. background: -ms-radial-gradient(circle, #eee, #666);
  17. }
  18. </style>
  19. <script>
  20. //js settings (see the skills.js for more)
  21. var url = '{{ url }}';
  22. //Block settings see the SkillVisualizer Class
  23. var offset_x = {{ skill_visualizer.offset_x }};
  24. var offset_y = {{ skill_visualizer.offset_y }};
  25. var space_between_blocks_x = {{ skill_visualizer.space_between_blocks_x }};
  26. var space_between_blocks_y = {{ skill_visualizer.space_between_blocks_y }};
  27. var center_x = {{ skill_visualizer.center_x }};
  28. var block_size = {{ skill_visualizer.block_size }};
  29. $(window).resize(function() {
  30. jsPlumb.repaintEverything();
  31. /*jsPlumb.repaint(".skill_root");
  32. // When resize repaint everything + fix the root position
  33. normal_weight = $('.skill_child :first-child').width();
  34. sum = $('body').width() / 2 - normal_weight/2;
  35. $('.skill_root').animate({ left: sum, top:0 }, { duration: 100 });*/
  36. });
  37. jsPlumb.ready(function() {
  38. //Setting the loading dialog
  39. var loading = $( "#dialog-loading" );
  40. loading.dialog( "destroy" );
  41. loading.dialog({
  42. autoOpen:false,
  43. height: 120,
  44. modal: true,
  45. zIndex: 10000,
  46. resizable :false,
  47. closeOnEscape : false,
  48. disabled: true,
  49. open: function(event, ui) { $(this).parent().children().children('.ui-dialog-titlebar-close').hide(); }
  50. });
  51. jQuery.ajaxSetup({
  52. beforeSend: function() {
  53. loading.dialog( "open" );
  54. //$('#skill_tree').hide();
  55. console.log('before------------------->>');
  56. },
  57. complete: function(){
  58. loading.dialog( "close" );
  59. //$('#skill_tree').show();
  60. console.log('complete------------------->>');
  61. },
  62. success: function() {}
  63. });
  64. //Return to root button
  65. $('#return_to_root').click(function(){
  66. clean_values();
  67. console.log('Clean values');
  68. console.log('Reopen the root ');
  69. });
  70. //Open dialog
  71. $("#dialog-form").dialog({
  72. autoOpen: false,
  73. modal : true,
  74. width : 550,
  75. height : 480
  76. });
  77. //Filling skills select
  78. /*
  79. $.getJSON("{{url}}&a=get_skills&parent_id="+parents[0], {},
  80. function(data) {
  81. $.each(data, function(n, parent) {
  82. // add a new option with the JSON-specified value and text
  83. $("<option />").attr("value", parent.id).text(parent.name).appendTo("#parent_id");
  84. });
  85. }
  86. );*/
  87. //Filling gradebook select
  88. $.getJSON("{{url}}&a=get_gradebooks", {},
  89. function(data) {
  90. $.each(data, function(n, gradebook) {
  91. // add a new option with the JSON-specified value and text
  92. $("<option />").attr("value", gradebook.id).text(gradebook.name).appendTo("#gradebook_id");
  93. });
  94. }
  95. );
  96. //Add button on click
  97. $("#add_item_link").click(function() {
  98. $("#name").attr('value', '');
  99. $("#description").attr('value', '');
  100. $("#parent_id option:selected").removeAttr('selected');
  101. $("#gradebook_id option:selected").removeAttr('selected');
  102. $("#dialog-form").dialog("open");
  103. //Filling skills select
  104. var my_id = 1;
  105. if (parents.length > 1) {
  106. my_id = parents[1].split('_')[1];
  107. }
  108. //Remove all options
  109. $("#parent_id").find('option').remove();
  110. $.getJSON("{{url}}&a=get_skills&id="+my_id, {
  111. },
  112. function(data) {
  113. $.each(data, function(n, parent) {
  114. // add a new option with the JSON-specified value and text
  115. $("<option />").attr("value", parent.id).text(parent.name).appendTo("#parent_id");
  116. });
  117. }
  118. );
  119. });
  120. //Add button process
  121. var name = $( "#name" ),
  122. description = $( "#description" ),
  123. allFields = $( [] ).add( name ).add( description ), tips = $(".validateTips");
  124. $("#dialog-form").css('z-index', '9001');
  125. $("#dialog-form").dialog({
  126. buttons: {
  127. "{{"Add"|get_lang}}" : function() {
  128. var bValid = true;
  129. bValid = bValid && checkLength( name, "name", 1, 255 );
  130. if (bValid) {
  131. var params = $("#add_item").serialize();
  132. $.ajax({
  133. async: false,
  134. url: url+'&a=add&'+params,
  135. success:function(my_id) {
  136. //Setting the selected id from the form
  137. parent_id = $("#parent_id option:selected").attr('value');
  138. //Reseting jsplumb
  139. jsPlumb.reset();
  140. //Deletes all windows
  141. $('.skill_root').remove();
  142. $('.skill_child').remove();
  143. //cleaning skills
  144. skills = [];
  145. //Setting the first parent
  146. first_parent = parents[0];
  147. //Deleting the first parent
  148. console.log('parents before '+parents);
  149. parents.splice(0,1);
  150. console.log('parents now '+parents);
  151. //Remove parent block
  152. $('#block_'+parent_id).remove();
  153. //Open the block
  154. open_block('block_'+parent_id, 0, 1);
  155. //Close dialog
  156. $("#dialog-form").dialog("close");
  157. }
  158. });
  159. }
  160. }
  161. },
  162. close: function() {
  163. $("#name").attr('value', '');
  164. $("#description").attr('value', '');
  165. }
  166. });
  167. //Clicking in a box skill (we use live instead of bind because we're creating divs on the fly )
  168. $(".open_block").click(function() {
  169. var id = $(this).attr('id');
  170. console.log('click.open_block id: ' + id);
  171. console.log('parents: ' + parents);
  172. //if is root
  173. if (parents[0] == id) {
  174. parents = [id];
  175. }
  176. if (parents[1] != id) {
  177. console.log('parents.length ' +parents.length);
  178. //If there are 2 parents in the skill_tree
  179. if (parents.length == 2 ) {
  180. first_parent = parents[0];
  181. $('#'+parents[1]).css('top', '0px');
  182. //console.log('deleting: '+parents[0]);
  183. //removing father
  184. console.log("first_parent " + first_parent);
  185. for (var i = 0; i < skills.length; i++) {
  186. //console.log('looping '+skills[i].element + ' ');
  187. if (skills[i].element == parents[0] ) {
  188. console.log('deleting parent:'+ skills[i].element + ' here ');
  189. jsPlumb.deleteEndpoint(skills[i].element);
  190. jsPlumb.detachAllConnections(skills[i].element);
  191. jsPlumb.removeAllEndpoints(skills[i].element);
  192. $("#"+skills[i].element).remove();
  193. }
  194. }
  195. parents.splice(0,1);
  196. parents.push(id);
  197. console.log('parents after slice/push: ' + parents);
  198. }
  199. if ($(this).hasClass('first_window')) {
  200. console.log('im in a first_window (root)');
  201. $('#'+first_parent).css('top', '0px');
  202. //show the first_parent
  203. //if (first_parent != '') {
  204. parents = [first_parent, id];
  205. open_parent(first_parent, id);
  206. //}
  207. }
  208. if (jQuery.inArray(id, parents) == -1) {
  209. parents.push(id);
  210. console.log('parents push: ' + parents);
  211. }
  212. open_block(id, 0, 0);
  213. }
  214. //Setting class
  215. cleanclass($(this));
  216. $(this).addClass('second_window');
  217. parent_div = $("#"+parents[0]);
  218. cleanclass(parent_div);
  219. parent_div.addClass('first_window');
  220. parent_div.addClass('skill_root');
  221. parent_div = $("#"+parents[1]);
  222. cleanclass(parent_div);
  223. parent_div.addClass('second_window');
  224. //console.log(parents);
  225. // console.log(skills);
  226. console.log('first_parent : ' + first_parent);
  227. //redraw
  228. jsPlumb.repaintEverything();
  229. jsPlumb.repaint(id);
  230. });
  231. //Skill title click
  232. $(".edit_block").click(function() {
  233. var my_id = $(this).attr('id');
  234. my_id = my_id.split('_')[2];
  235. //Cleaning selected
  236. $("#parent_id option:selected").removeAttr('selected');
  237. $("#gradebook_id option:selected").removeAttr('selected');
  238. $.ajax({
  239. url: url+'&a=get_skill_info&id='+my_id,
  240. success: function(json) {
  241. var skill = jQuery.parseJSON(json);
  242. $("#name").attr('value', skill.name);
  243. $("#id").attr('value', skill.id);
  244. $("#description").attr('value', skill.description);
  245. //filling parent_id
  246. $("#parent_id option[value='"+skill.extra.parent_id+"']").attr('selected', 'selected');
  247. //filling the gradebook_id
  248. jQuery.each(skill.gradebooks, function(index, data) {
  249. $("#gradebook_id option[value='"+data.id+"']").attr('selected', 'selected');
  250. });
  251. }
  252. });
  253. $("#gradebook_id").trigger("liszt:updated");
  254. $("#parent_id").trigger("liszt:updated");
  255. $("#dialog-form").dialog("open");
  256. return false;
  257. });
  258. //Clicking in a box
  259. $(".window").bind('click', function() {
  260. var id = $(this).attr('id');
  261. id = id.split('_')[1];
  262. });
  263. // chrome fix.
  264. document.onselectstart = function () { return false; };
  265. // render mode
  266. var resetRenderMode = function(desiredMode) {
  267. var newMode = jsPlumb.setRenderMode(desiredMode);
  268. jsPlumbDemo.init();
  269. };
  270. resetRenderMode(jsPlumb.CANVAS);
  271. });
  272. ;(function() {
  273. prepare = function(div, endpointOptions) {
  274. console.log('preparing = '+div);
  275. console.log('endpointOptions = '+endpointOptions);
  276. //jsPlumbDemo.initHover(elId);
  277. var endPoint = jsPlumb.addEndpoint(div, endpointOptions);
  278. skills.push({
  279. element: div, endp:endPoint
  280. });
  281. return endPoint;
  282. },
  283. window.jsPlumbDemo = {
  284. init : function() {
  285. console.log('Import defaults');
  286. jsPlumb.Defaults.Anchors = [ "BottomCenter", "TopCenter" ];
  287. jsPlumb.Defaults.Container = "skill_tree";
  288. open_block('block_1', 0, 1);
  289. // listen for clicks on connections, and offer to delete connections on click.
  290. jsPlumb.bind("click", function(conn, originalEvent) {
  291. /*if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?"))
  292. jsPlumb.detach(conn); */
  293. });
  294. }
  295. };
  296. })();
  297. $(document).ready(function() {
  298. /*
  299. //When creating a connection see
  300. //http://jsplumb.org/apidocs/files/jsPlumb-1-3-2-all-js.html#bind
  301. jsPlumb.bind("jsPlumbConnection", function(conn) {
  302. //alert("Connection created " + conn.sourceId + " to " + conn.targetId + " ");
  303. //jsPlumb.detach(conn);
  304. });
  305. //When double clicking a connection
  306. jsPlumb.bind("click", function(conn) {
  307. if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?"))
  308. jsPlumb.detach(conn);
  309. });
  310. //When double clicking a connection
  311. jsPlumb.bind("click", function(endpoint) {
  312. if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?"))
  313. jsPlumb.detach(conn);
  314. });*/
  315. $(".chzn-select").chosen();
  316. $("#menu").draggable();
  317. });
  318. ;(function() {
  319. jsPlumbDemo.getSelector = function(spec) {
  320. return $(spec);
  321. };
  322. jsPlumbDemo.attachBehaviour = function() {
  323. $(".hide").click(function() {
  324. jsPlumb.toggle($(this).attr("rel"));
  325. });
  326. $(".drag").click(function() {
  327. var s = jsPlumb.toggleDraggable($(this).attr("rel"));
  328. $(this).html(s ? 'disable dragging' : 'enable dragging');
  329. if (!s) $("#" + $(this).attr("rel")).addClass('drag-locked'); else $("#" + $(this).attr("rel")).removeClass('drag-locked');
  330. $("#" + $(this).attr("rel")).css("cursor", s ? "pointer" : "default");
  331. });
  332. $(".detach").click(function() {
  333. jsPlumb.detachAll($(this).attr("rel"));
  334. });
  335. $("#clear").click(function() {
  336. jsPlumb.detachEverything(); showConnections();
  337. });
  338. };
  339. })();
  340. </script>
  341. <div id="dialog-loading">
  342. <div class="modal-body">
  343. <p style="text-align:center">
  344. {{ "Loading"|get_lang }}
  345. <img src="{{ _p.web_img}}loadingAnimation.gif"/>
  346. </p>
  347. </div>
  348. </div>
  349. <div id="menu" class="well" style="top:20px; left:20px; width:380px; z-index: 9000; opacity: 0.9;">
  350. <h3>{{'Skills'|get_lang}}</h3>
  351. <div class="btn-group">
  352. <a style="z-index: 1000" class="btn" id="add_item_link" href="#">{{'AddSkill'|get_lang}}</a>
  353. <a style="z-index: 1000" class="btn btn-default" id="return_to_root" href="#">{{'Root'|get_lang}}</a>
  354. <a style="z-index: 1000" class="btn btn-default" id="return_to_admin" href="{{_p.web_main}}admin">{{'BackToAdmin'|get_lang}}</a>
  355. </div>
  356. </div>
  357. <div id="skill_tree"></div>
  358. <div id="dialog-form" style="display:none; z-index:9001;">
  359. <p class="validateTips"></p>
  360. <form class="form-horizontal" id="add_item" name="form">
  361. <fieldset>
  362. <input type="hidden" name="id" id="id"/>
  363. <div class="control-group">
  364. <label class="control-label" for="name">{{'Name'|get_lang}}</label>
  365. <div class="controls">
  366. <input type="text" name="name" id="name" size="40" />
  367. </div>
  368. </div>
  369. <div class="control-group">
  370. <label class="control-label" for="name">{{'Parent'|get_lang}}</label>
  371. <div class="controls">
  372. <select id="parent_id" name="parent_id" />
  373. </select>
  374. </div>
  375. </div>
  376. <div class="control-group">
  377. <label class="control-label" for="name">{{'Gradebook'|get_lang}}</label>
  378. <div class="controls">
  379. <select id="gradebook_id" name="gradebook_id[]" multiple="multiple"/>
  380. </select>
  381. <span class="help-block">
  382. {{'WithCertificate'|get_lang}}
  383. </span>
  384. </div>
  385. </div>
  386. <div class="control-group">
  387. <label class="control-label" for="name">{{'Description'|get_lang}}</label>
  388. <div class="controls">
  389. <textarea name="description" id="description" rows="7"></textarea>
  390. </div>
  391. </div>
  392. </fieldset>
  393. </form>
  394. </div>