A medida que las webs se van complicando, sobre todo en las páginas modernas, van necesitando más y más archivos Javascript para poder ejecutarse, y lo malo es que estos archivos deben incluirse por orden, ya que un mínimo fallo aquí puede hacer que nuestra aplicación web no funcione correctamente. Por otro lado, también tenemos el caso de que para incluir un script, debemos incluir también varias dependencias (algunas obligatorias, otras opcionales).
Con esta clase quiero hacer una primera aproximación a la solución del problema:
myjs.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | <?php /** ************************************************************* * @file myjs.class.php *************************************************************/ class Myjs { protected $commonScripts = array('lib/backbone' => array('aliases' => array('backbone', 'bkbn'), 'depends' => array('!underscore', 'jquery'), ), 'lib/jquery-ui' => array('aliases' => array('jquery-ui', 'jqueryui'), 'depends' => array('!jquery') ), 'lib/jquery' => array('aliases' => array('jquery', '$'), ), 'lib/underscore' => array('aliases' => array('underscore')), 'myscript' => array('depends' => array('!backbone', 'jquery', '!jqueryui', '!extraDepend')), 'lib/contextMenu' => array('aliases' => array('contextMenu', 'context'), 'depends' => array('!jquery-ui', 'jquery',)), ); protected $scripts = array(); /** * Finds script in commonScripts array * * @param $script Script to find */ private function findScript($script) { if (isset($this->commonScripts[$script])) return $script; foreach ($this->commonScripts as $_script => $options) { if (isset($options['aliases'])) { if (in_array($script, $options['aliases'])) return $_script; } } return false; } /** * Adds a new Javascript to our project * * @param $script Script name or path * @param $options Script options */ function addScript($script, $options = array()) { $foundScript = $this->findScript($script); if ($foundScript) $script = $foundScript; /* The script has already been added */ if (isset($this->scripts[$script])) return; if ($foundScript) { /* Merge dependencies from commonscripts and dependencies given by the user */ $options['depends'] = array_merge((isset($this->commonScripts[$foundScript]['depends']))?$this->commonScripts[$foundScript]['depends']:array(), (isset($options['depends']))?$options['depends']:array()); } else $options['depends'] = array(); foreach ($options['depends'] as $depend) { if ($depend[0]=='!') $this->addScript(substr($depend, 1)); } $this->scripts[$script] = $options; } /** * Ask an script if there is any other script before him * * @param $script Script to ask to * @param $script options * @param $ordered Array of ordered scripts */ function askScript($script, $options, &$ordered) { if (in_array($script, $ordered)) return; if (!empty($options['depends'])) { foreach ($options['depends'] as $dep) { if (isset($this->scripts[$dep])) { $this->askScript($this->scripts[$dep], $ordered); } } } $ordered[] = $script; } /** * Writes <script type="text/javascript" src="scriptpath.js"></script> for each * javascript file, in order. * */ function sendScripts() { if (empty($this->scripts)) return ''; $ordered = array(); foreach ($this->scripts as $script => $options) { $this->askScript($script, $options, $ordered); } $out=''; foreach ($ordered as $script) { $out.='<script type="text/javascript" src="/js/'.$script.'.js"></script>'."\n"; } return $out; } /** * Return scripts array (debug only) * */ function scriptsArray() { return $this->scripts; } } ?> |
Al principio tenemos un array ($commonScripts), aquí pondremos información relativa a los javascripts que vamos incluyendo, como claves, debemos poner la ruta donde se encuentra el archivo javascript, el valor será un array donde podremos incluir:
- aliases : Un array con las posibles formas que tendremos de llamar al script, por ejemplo, el nombre sin la ruta, omitiendo algunos símbolos, por ejemplo si incluimos jquery.min, podemos llamarlo directamente jquery
- depends : Array con las dependencias, en este casi si la dependencia es obligatoria, debemos poner una exclamación (!) delante del archivo, para que éste también se incluya en el proyecto
Podríamos incluir algunas cosas más, por ejemplo una opción que incluya el script sólo en Internet Explorer , o dependiendo de la versión de Internet Explorer, para poder incluir hacks como html5shiv o json2, etc o que el archivo javascript incluya también archivos CSS (pero esto no está implementado en el ejemplo)
El método addScript() tendrá dos argumentos, por un lado el script y por otro las opciones (que son idénticas a los valores del array $commonScripts. Este método incluirá el archivo que se ha pedido y buscará las dependencias obligatorias para incluirlas también.
La gran funcionalidad del script reside en sendScripts() y askScript(), entre los dos repasan todos los Javascripts incluidos para ponerlos en orden, askScript, de forma recursiva, va comprobando las dependencias de cada uno de ellos, y cuando un script no tiene dependencias pendientes, se añade al array $ordered. Luego, desde sendScripts, se recorre el array $ordered y se envía la cadena necesaria para incluir los scripts.
Podemos hacer un pequeño script de prueba:
test.php
1 2 3 4 5 6 7 8 9 10 11 | <?php require_once("myjs.class.php"); $s = new Myjs(); $s->addScript('context'); $s->addScript('myscript'); echo $s->sendScripts(); ?> |
Podemos jugar con la forma en la que incluimos los scripts, incluirlos en diferente orden, o incluir sólo los scripts principales que queremos en nuestro programa, para que las dependencias se incluyan solas.
Actualización 14/10/2016 : Añadida foto principal.
Foto principal: Massimo Mancini
Pingback: Bitacoras.com /
I really like the way that you have expressed yourself. There is a lot to be admired from this post. You might want to click onDavid Martinez Jacket