renderer.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Competence Graph
  18. *
  19. * Competence graph format allows the visualization of courses with competencies in a graph.
  20. * In the course structure, teacher associates activities to competencies. Each course module
  21. * can have restrictions between them, so a module is opened only when the student accomplish
  22. * its requirements. In student visualization, the structure of the course is presented as a
  23. * graph. In such graph, each node is a resource available to the student that can be handled.
  24. * Subgraphs in the main graph represent competences. As students can have different paths in
  25. * the course, the plugin registers all the steps that a student produces.
  26. *
  27. * @package course/format
  28. * @subpackage competencegraph
  29. * @version 0.1
  30. * @author Laboratório de Informática na Educação <http://www.usp.br/line>
  31. * @link http://www.usp.br/line/competencegraph
  32. * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  33. */
  34. defined('MOODLE_INTERNAL') || die();
  35. use core_competency\course_competency;
  36. use core_competency\api;
  37. use core_competency\course_module_competency;
  38. require_once($CFG->dirroot . '/course/format/renderer.php');
  39. require_once($CFG->dirroot . '/course/format/competencegraph/lib.php');
  40. class format_competencegraph_renderer extends format_section_renderer_base {
  41. public function __construct(moodle_page $page, $target) {
  42. parent::__construct($page, $target);
  43. global $PAGE;
  44. //$this->courserenderer = $PAGE->get_renderer('core','course');
  45. $this->togglelib = new \format_topcoll\togglelib;
  46. $this->courseformat = course_get_format($page->course); // Needed for collapsed topics settings retrieval.
  47. $page->set_other_editing_capability('moodle/course:setcurrentsection');
  48. $this->userisediting = $page->user_is_editing();
  49. $this->rtl = right_to_left();
  50. if (strcmp($page->theme->name, 'boost') === 0) {
  51. $this->bsnewgrid = true;
  52. } else if (!empty($page->theme->parents)) {
  53. if (in_array('boost', $page->theme->parents) === true) {
  54. $this->bsnewgrid = true;
  55. }
  56. }
  57. }
  58. protected function start_section_list() {
  59. if ($this->bsnewgrid) {
  60. return html_writer::start_tag('ul', array('class' => 'ctopics bsnewgrid'));
  61. } else {
  62. return html_writer::start_tag('ul', array('class' => 'ctopics'));
  63. }
  64. }
  65. protected function end_section_list() {
  66. return html_writer::end_tag('ul');
  67. }
  68. protected function page_title() {
  69. return get_string('sectionname', 'format_competencegrah');
  70. }
  71. public function set_portable($portable) {
  72. switch ($portable) {
  73. case 1:
  74. $this->mobiletheme = true;
  75. break;
  76. case 2:
  77. $this->tablettheme = true;
  78. break;
  79. default:
  80. $this->mobiletheme = false;
  81. $this->tablettheme = false;
  82. break;
  83. }
  84. }
  85. public function print_graph_teacher_view($course, $sections, $mods, $modnames, $modnamesused) {
  86. $context = context_course::instance($course->id);
  87. if (has_capability('moodle/course:update', $context)) {
  88. $maintabs = array(
  89. new tabobject( 'tab_list', '?id='.$course->id.'&format=list', get_string('listview', 'format_competencegraph'), get_string('listview', 'format_competencegraph') ),
  90. new tabobject( 'tab_graph', '?id='.$course->id.'&format=graph', get_string('graphview', 'format_competencegraph'), get_string('graphview', 'format_competencegraph') )
  91. );
  92. $active = 'tab_graph';
  93. print_tabs( array($maintabs), $active );
  94. echo $this->get_js_dependencies_sigma_graph();
  95. $this->print_test_graph($course, $sections, $mods, $modnames, $modnamesused);
  96. }
  97. }
  98. public function print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused) {
  99. $context = context_course::instance($course->id);
  100. $colors = ['#617db4', '#668f3c', '#c6583e', '#b956af', '#fcba03', '#03fcf0', '#fc0339', '#a6ffc8', '#000000'];
  101. if (has_capability('moodle/course:update', $context)) {
  102. // Print the competencies as name section:
  103. $list_competencies = course_competency::list_course_competencies($course->id);
  104. $all_mod_info_printed = array();
  105. $modinfo = get_fast_modinfo($course);
  106. $count = 0;
  107. foreach ($list_competencies as $competence) {
  108. $idcompetence = $competence->get('competencyid');
  109. api::read_competency($idcompetence)->get('shortname');
  110. $list_modules = course_module_competency::list_course_modules($idcompetence, $course->id);
  111. foreach ($list_modules as $item) {
  112. array_push($all_mod_info_printed, $item);
  113. }
  114. foreach ($list_modules as $modnumber) {
  115. $mod = $modinfo->cms[$modnumber];
  116. echo "g.nodes.push({
  117. id: 'n".($mod->id . $count)."',
  118. label: '".$mod->name."',
  119. x: Math.random(),
  120. y: Math.random(),
  121. size: 1,
  122. color: '".$colors[$count]."'
  123. });\n";
  124. }
  125. $count++;
  126. }
  127. $list_mod_without_competences = array();
  128. foreach ($modinfo->cms as $tempmod) {
  129. if (!in_array($tempmod->id, $all_mod_info_printed)) {
  130. array_push($list_mod_without_competences, $tempmod->id);
  131. }
  132. }
  133. }
  134. }
  135. public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
  136. $context = context_course::instance($course->id);
  137. global $OUTPUT;
  138. if (has_capability('moodle/course:update', $context)) {
  139. echo $this->get_css_list_teacher();
  140. //$this->print_modules_page_teacher_list($course, $sections, $mods, $modnames, $modnamesused);
  141. $modinfo = get_fast_modinfo($course);
  142. $course = $this->courseformat->get_course();
  143. $context = context_course::instance($course->id);
  144. $sections = $modinfo->get_section_info_all();
  145. // General section if non-empty.
  146. $thissection = $sections[0];
  147. if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) {
  148. print('<div class="tohidden firstitem">');
  149. echo $this->section_header($thissection, $course, false, 0);
  150. print('</div>');
  151. echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  152. }
  153. $maintabs = array(
  154. new tabobject( 'tab_list', '?id='.$course->id.'&format=list', get_string('listview', 'format_competencegraph'), get_string('listview', 'format_competencegraph') ),
  155. new tabobject( 'tab_graph', '?id='.$course->id.'&format=graph', get_string('graphview', 'format_competencegraph'), get_string('graphview', 'format_competencegraph') )
  156. );
  157. $active = 'tab_list';
  158. print_tabs( array($maintabs), $active );
  159. // Print the competencies as name section:
  160. $list_competencies = course_competency::list_course_competencies($course->id);
  161. if (count($list_competencies) < 1) {
  162. echo '<div class="coursewithoutcompetence"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>' . get_string('coursewithoutcompetence', 'format_competencegraph') . '</div>';
  163. }
  164. $all_mod_info_printed = array();
  165. foreach ($list_competencies as $competence) {
  166. $idcompetence = $competence->get('competencyid');
  167. echo '<h4 class="sectionname"><span><a href="#">' . api::read_competency($idcompetence)->get('shortname') . '</a></span></h4>';
  168. $list_modules = course_module_competency::list_course_modules($idcompetence, $course->id);
  169. if (!$list_modules || count($list_modules) < 1) {
  170. echo '<div class="emptycompetence"><i class="fa fa-info-circle" aria-hidden="true"></i>' . get_string('emptycompetence', 'format_competencegraph') . "</div>";
  171. }
  172. echo $this->course_section_cm_list($course, null, 0, array(), $list_modules);
  173. foreach ($list_modules as $item) {
  174. array_push($all_mod_info_printed, $item);
  175. }
  176. }
  177. $list_mod_without_competences = array();
  178. foreach ($modinfo->cms as $tempmod) {
  179. if (!in_array($tempmod->id, $all_mod_info_printed)) {
  180. array_push($list_mod_without_competences, $tempmod->id);
  181. }
  182. }
  183. if (count($list_mod_without_competences) > 0) {
  184. echo '<h4 class="withoutcompetence"><span><a href="#">' . get_string('itemswithoutcompetence', 'format_competencegraph') . '</a></span></h4>';
  185. echo $this->course_section_cm_list($course, null, 0, array(), $list_mod_without_competences);
  186. }
  187. $sections = $modinfo->get_section_info_all();
  188. // General section if non-empty.
  189. $thissection = $sections[0];
  190. if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) {
  191. print('<div class="tohidden">');
  192. echo $this->section_header($thissection, $course, false, 0);
  193. print('</div>');
  194. echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  195. }
  196. }
  197. }
  198. public function course_section_cm_list($course, $section, $sectionreturn = null, $displayoptions = array(), $includeditems = array()) {
  199. global $USER;
  200. $output = '';
  201. $modinfo = get_fast_modinfo($course);
  202. $completioninfo = new completion_info($course);
  203. // check if we are currently in the process of moving a module with JavaScript disabled
  204. $ismoving = $this->page->user_is_editing() && ismoving($course->id);
  205. if ($ismoving) {
  206. $movingpix = new pix_icon('movehere', get_string('movehere'), 'moodle', array('class' => 'movetarget'));
  207. $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'"));
  208. }
  209. // Get the list of modules visible to user (excluding the module being moved if there is one)
  210. $moduleshtml = array();
  211. foreach ($includeditems as $modnumber) {
  212. $mod = $modinfo->cms[$modnumber];
  213. if ($mod->availability)
  214. echo $modnumber . ':: ';
  215. print_r($mod->availability);
  216. if ($ismoving and $mod->id == $USER->activitycopy) {
  217. // do not display moving mod
  218. continue;
  219. }
  220. if ($modulehtml = $this->courserenderer->course_section_cm_list_item($course,
  221. $completioninfo, $mod, $sectionreturn, $displayoptions)) {
  222. $moduleshtml[$modnumber] = $modulehtml;
  223. }
  224. }
  225. $sectionoutput = '';
  226. if (!empty($moduleshtml) || $ismoving) {
  227. foreach ($moduleshtml as $modnumber => $modulehtml) {
  228. if ($ismoving) {
  229. $movingurl = new moodle_url('/course/mod.php', array('moveto' => $modnumber, 'sesskey' => sesskey()));
  230. $sectionoutput .= html_writer::tag('li',
  231. html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)),
  232. array('class' => 'movehere'));
  233. }
  234. $sectionoutput .= $modulehtml;
  235. }
  236. if ($ismoving) {
  237. $movingurl = new moodle_url('/course/mod.php', array('movetosection' => $section->id, 'sesskey' => sesskey()));
  238. $sectionoutput .= html_writer::tag('li',
  239. html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)),
  240. array('class' => 'movehere'));
  241. }
  242. }
  243. // Always output the section module list.
  244. $output .= html_writer::tag('ul', $sectionoutput, array('class' => 'section img-text'));
  245. return $output;
  246. }
  247. public function print_modules_page_teacher_list($course, $sections, $mods, $modnames, $modnamesused) {
  248. $modinfo = get_fast_modinfo($course);
  249. $course = $this->courseformat->get_course();
  250. $context = context_course::instance($course->id);
  251. //echo $this->start_section_list();
  252. $sections = $modinfo->get_section_info_all();
  253. // General section if non-empty.
  254. $thissection = $sections[0];
  255. if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) {
  256. echo $this->section_header($thissection, $course, false, 0);
  257. //echo $this->course_section_cm_list($course, $thissection, 0);
  258. echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  259. }
  260. $coursenumsections = $this->courseformat->get_last_section_number();
  261. if ($coursenumsections > 0) {
  262. $sectiondisplayarray = array();
  263. $currentsectionfirst = false;
  264. if ((!$this->userisediting)) {
  265. $currentsectionfirst = true;
  266. }
  267. if (($this->userisediting)) {
  268. $section = 1;
  269. } else {
  270. $timenow = time();
  271. $weekofseconds = 604800;
  272. $course->enddate = $course->startdate + ($weekofseconds * $coursenumsections);
  273. $section = $coursenumsections;
  274. $weekdate = $course->enddate; // This should be 0:00 Monday of that week.
  275. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems.
  276. }
  277. $numsections = $coursenumsections; // Because we want to manipulate this for column breakpoints.
  278. if (($this->userisediting == false)) {
  279. $loopsection = 1;
  280. $numsections = 0;
  281. while ($loopsection <= $coursenumsections) {
  282. $nextweekdate = $weekdate - ($weekofseconds);
  283. if ((($thissection->uservisible ||
  284. ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo))) &&
  285. ($nextweekdate <= $timenow)) == true) {
  286. $numsections++; // Section not shown so do not count in columns calculation.
  287. }
  288. $weekdate = $nextweekdate;
  289. $section--;
  290. $loopsection++;
  291. }
  292. // Reset.
  293. $section = $coursenumsections;
  294. $weekdate = $course->enddate; // This should be 0:00 Monday of that week.
  295. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems.
  296. }
  297. echo $this->end_section_list();
  298. $loopsection = 1;
  299. $breaking = false; // Once the first section is shown we can decide if we break on another column.
  300. while ($loopsection <= $coursenumsections) {
  301. $thissection = $modinfo->get_section_info($section);
  302. /* Show the section if the user is permitted to access it, OR if it's not available
  303. but there is some available info text which explains the reason & should display. */
  304. if (($this->userisediting)) {
  305. $showsection = $thissection->uservisible ||
  306. ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo));
  307. } else {
  308. $showsection = ($thissection->uservisible ||
  309. ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo))) &&
  310. ($nextweekdate <= $timenow);
  311. }
  312. if (($currentsectionfirst == true) && ($showsection == true)) {
  313. // Show the section if we were meant to and it is the current section:....
  314. $showsection = ($course->marker == $section);
  315. }
  316. if (!$showsection) {
  317. // Hidden section message is overridden by 'unavailable' control.
  318. $testhidden = false;
  319. if ($testhidden) {
  320. if (!$course->hiddensections && $thissection->available) {
  321. $thissection->ishidden = true;
  322. $sectiondisplayarray[] = $thissection;
  323. }
  324. }
  325. } else {
  326. $thissection->isshown = true;
  327. $sectiondisplayarray[] = $thissection;
  328. }
  329. if (($this->userisediting)) {
  330. $section++;
  331. } else {
  332. $section--;
  333. if (($this->userisediting == false)) {
  334. $weekdate = $nextweekdate;
  335. }
  336. }
  337. $loopsection++;
  338. if (($currentsectionfirst == true) && ($loopsection > $coursenumsections)) {
  339. // Now show the rest.
  340. $currentsectionfirst = false;
  341. $loopsection = 1;
  342. $section = 1;
  343. }
  344. if ($section > $coursenumsections) {
  345. // Activities inside this section are 'orphaned', this section will be printed as 'stealth' below.
  346. break;
  347. }
  348. }
  349. if ((!$this->userisediting) && (!empty($this->currentsection))) {
  350. $shownonetoggle = $this->currentsection; // One toggle open only, so as we have a current section it will be it.
  351. }
  352. foreach ($sectiondisplayarray as $thissection) {
  353. if (!empty($thissection->ishidden)) {
  354. echo $this->section_hidden($thissection);
  355. } else if (!empty($thissection->issummary)) {
  356. echo $this->section_summary($thissection, $course, null);
  357. } else if (!empty($thissection->isshown)) {
  358. //echo $this->section_header($thissection, $course, false, 0);
  359. if ($thissection->uservisible) {
  360. //echo $this->course_section_cm_list($course, $thissection, 0);
  361. //echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  362. }
  363. echo html_writer::end_tag('div');
  364. }
  365. unset($sections[$thissection->section]);
  366. }
  367. }
  368. }
  369. private function get_css_list_teacher() {
  370. $style = "<style>";
  371. $style .= ".sectionname, .withoutcompetence {
  372. border-top: 1px solid #cfdacf;
  373. margin-top: 1em;
  374. padding-top: .3em;
  375. }
  376. .emptycompetence {
  377. margin-left: 1.5em;
  378. opacity: .8;
  379. }
  380. .emptycompetence i {
  381. margin-right: .5em;
  382. }
  383. .tohidden .right.side {
  384. display: none;
  385. }
  386. .tohidden li {
  387. list-style-type: none;
  388. }
  389. .coursewithoutcompetence {
  390. border: 1px solid gray;
  391. padding: 1em;
  392. border-radius: .5em;
  393. margin: 1em;
  394. color: #c63100;
  395. }
  396. .coursewithoutcompetence i {
  397. opacity: .8;
  398. margin-right: .5em;
  399. }
  400. .firstitem .section-modchooser-link {
  401. float: right;
  402. }";
  403. return $style . "</style>";
  404. }
  405. private function print_test_graph($course, $sections, $mods, $modnames, $modnamesused) {
  406. echo '<div id="container">
  407. <style>
  408. #graph-container {
  409. top: 0;
  410. bottom: 0;
  411. left: 0;
  412. right: 0;
  413. position: absolute;
  414. }
  415. </style>
  416. <div id="graph-container"></div>
  417. </div>';
  418. echo "<script>
  419. // generate a random graph
  420. var i,
  421. s,
  422. img,
  423. N = 10,
  424. E = 50,
  425. g = {
  426. nodes: [],
  427. edges: []
  428. },
  429. colors = [
  430. '#617db4',
  431. '#668f3c',
  432. '#c6583e',
  433. '#b956af'
  434. ];";
  435. $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused);
  436. echo "
  437. /*for (i = 0; i < E; i++) {
  438. g.edges.push({
  439. id: 'e' + i,
  440. source: 'n' + (Math.random() * N | 0),
  441. target: 'n' + (Math.random() * N | 0),
  442. type: ['arrow'][0],
  443. size: 1,
  444. color: '#bdbdbd'
  445. });
  446. }*/
  447. s = new sigma({
  448. graph: g,
  449. renderer: {
  450. // IMPORTANT:
  451. // This works only with the canvas renderer, so the
  452. // renderer type set as canvas is necessary here.
  453. container: document.getElementById('graph-container'),
  454. type: 'canvas'
  455. },
  456. settings: {
  457. minNodeSize: 1,
  458. maxNodeSize: 10,
  459. minEdgeSize: 0.1,
  460. maxEdgeSize: 2,
  461. enableEdgeHovering: true,
  462. edgeHoverSizeRatio: 2
  463. }
  464. });
  465. </script>
  466. ";
  467. }
  468. private function get_js_dependencies_sigma_graph() {
  469. global $CFG;
  470. $dirjs = $CFG->wwwroot . '/course/format/competencegraph/js/sigma';
  471. $o = '<script src="'.$dirjs.'/src/sigma.core.js"></script>
  472. <script src="'.$dirjs.'/src/conrad.js"></script>
  473. <script src="'.$dirjs.'/src/utils/sigma.utils.js"></script>
  474. <script src="'.$dirjs.'/src/utils/sigma.polyfills.js"></script>
  475. <script src="'.$dirjs.'/src/sigma.settings.js"></script>
  476. <script src="'.$dirjs.'/src/classes/sigma.classes.dispatcher.js"></script>
  477. <script src="'.$dirjs.'/src/classes/sigma.classes.configurable.js"></script>
  478. <script src="'.$dirjs.'/src/classes/sigma.classes.graph.js"></script>
  479. <script src="'.$dirjs.'/src/classes/sigma.classes.camera.js"></script>
  480. <script src="'.$dirjs.'/src/classes/sigma.classes.quad.js"></script>
  481. <script src="'.$dirjs.'/src/classes/sigma.classes.edgequad.js"></script>
  482. <script src="'.$dirjs.'/src/captors/sigma.captors.mouse.js"></script>
  483. <script src="'.$dirjs.'/src/captors/sigma.captors.touch.js"></script>
  484. <script src="'.$dirjs.'/src/renderers/sigma.renderers.canvas.js"></script>
  485. <script src="'.$dirjs.'/src/renderers/sigma.renderers.webgl.js"></script>
  486. <script src="'.$dirjs.'/src/renderers/sigma.renderers.svg.js"></script>
  487. <script src="'.$dirjs.'/src/renderers/sigma.renderers.def.js"></script>
  488. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.nodes.def.js"></script>
  489. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.nodes.fast.js"></script>
  490. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.def.js"></script>
  491. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.fast.js"></script>
  492. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.arrow.js"></script>
  493. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.labels.def.js"></script>
  494. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.hovers.def.js"></script>
  495. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.nodes.def.js"></script>
  496. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.def.js"></script>
  497. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.curve.js"></script>
  498. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.arrow.js"></script>
  499. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.curvedArrow.js"></script>
  500. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.def.js"></script>
  501. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.curve.js"></script>
  502. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.arrow.js"></script>
  503. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.curvedArrow.js"></script>
  504. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.extremities.def.js"></script>
  505. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.utils.js"></script>
  506. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.nodes.def.js"></script>
  507. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.edges.def.js"></script>
  508. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.edges.curve.js"></script>
  509. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.labels.def.js"></script>
  510. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.hovers.def.js"></script>
  511. <script src="'.$dirjs.'/src/middlewares/sigma.middlewares.rescale.js"></script>
  512. <script src="'.$dirjs.'/src/middlewares/sigma.middlewares.copy.js"></script>
  513. <script src="'.$dirjs.'/src/misc/sigma.misc.animation.js"></script>
  514. <script src="'.$dirjs.'/src/misc/sigma.misc.bindEvents.js"></script>
  515. <script src="'.$dirjs.'/src/misc/sigma.misc.bindDOMEvents.js"></script>
  516. <script src="'.$dirjs.'/src/misc/sigma.misc.drawHovers.js"></script>
  517. <!-- END SIGMA IMPORTS -->
  518. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.dashed.js"></script>
  519. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.dotted.js"></script>
  520. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.parallel.js"></script>
  521. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.tapered.js"></script>
  522. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.dashed.js"></script>
  523. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.dotted.js"></script>
  524. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.parallel.js"></script>
  525. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.tapered.js"></script>';
  526. return $o;
  527. }
  528. }