├── .gitignore ├── .travis.yml ├── LICENCIA ├── README.md ├── TODO.md ├── code-es6 ├── count-server.js ├── express-count.js ├── github-get-largo.js ├── package.json ├── servidor-var.js ├── servidor.js └── sumar_formulario.html ├── code ├── Nuevo_partido.js ├── Partido.js ├── Quiniela.js ├── Resultado.js ├── Resultados.js ├── Un_Partido.js ├── aap-nav.user.js ├── bg-1.user.js ├── bg-2.js ├── bg-2.user.js ├── bg-3.js ├── bg-3.user.js ├── blogalia.user.js ├── calc.gm.js ├── calc.user.js ├── check-with-all.sh ├── contadores.js ├── count-server-var.js ├── count-server.js ├── crea-contadores.js ├── create-attachment.js ├── create-doc-bulk.js ├── create-doc-simple.js ├── cuenta-ajax.js ├── cuenta-jquery.js ├── di_resultado.js ├── docwrite.html ├── express-count.js ├── express-rest-server.js ├── formulario-jquery.html ├── funciones-anon.js ├── funciones.js ├── g.js ├── geonames_call.js ├── get-doc.js ├── github-get-largo.js ├── github-get.js ├── guenas-nave.js ├── guenas.js ├── hola-all.js ├── hola-browser-2.js ├── hola-browser.js ├── hola-g.js ├── hola-js-2.html ├── hola-js-3.html ├── hola-js.cgi ├── hola-js.html ├── hola.js ├── holak.js ├── holakase.js ├── holasincabecera.js ├── inc-contadores.js ├── index.html ├── inserta-resultados.js ├── json-geonames.html ├── jsr_class.js ├── kk-1.user.js ├── lee-quiniela.js ├── lee_quiniela.js ├── liga.js ├── liga2.js ├── liga3.js ├── list-quiniela.js ├── location.html ├── map.js ├── node-server-example.js ├── node_quiniela.js ├── node_twitter.js ├── onload.html ├── partidos.datos ├── peticion.js ├── putBloque.js ├── quiniela ├── quiniela-view.js ├── quiniela.datos ├── quiniela.js ├── quiniela2.js ├── ready-simple.html ├── ready.html ├── request.js ├── rest-client-js.html ├── rest-client.js ├── rest-minimo.js ├── rest-server-js.html ├── rest-server.js ├── selectores.html ├── servidor-var.js ├── servidor.js ├── sumar_formulario.html ├── tabla-final.js ├── tabla.js ├── tabla1.js ├── tabla2.js ├── usa_partido.js └── windowopen.html ├── js.css ├── metadata.xml ├── txt ├── 1-intro.md ├── 1-oo.md ├── 2-JQuery.md ├── 2-js-navegador.md ├── 3-node.md ├── 4-rest-ajax.md ├── 99-glosario.md ├── aprendeJS.txt ├── imagenes │ ├── AAP-DOM.png │ ├── by-sa.png │ ├── chromium-consola.png │ ├── firefox-consola.png │ ├── gjs-consola.png │ ├── node-consola.png │ └── nuevonodo.png ├── prologo.md ├── snippet.css └── words.dic └── utils ├── md2epub ├── md2html └── md2pdf /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.epub 3 | txt/html 4 | txt/pdf 5 | *.pdf 6 | *.temp 7 | code/highlight.css 8 | intro.html 9 | .idea 10 | code/node_modules/ 11 | code-es6/node_modules/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | branches: 4 | except: 5 | - gh-pages 6 | language: perl 7 | perl: 8 | - "5.16" 9 | before_install: 10 | - sudo apt-get update -qq 11 | - sudo apt-get -y install libhunspell-1.3-0 libhunspell-dev 12 | - curl https://raw.githubusercontent.com/JJ/Test-Text/master/data/Spanish.aff -o Spanish.aff 13 | - curl https://raw.githubusercontent.com/SublimeText/Dictionaries/master/Spanish.dic -o Spanish.dic 14 | - echo "use Test::Text;just_check( 'txt','.', 'Spanish' );" > just_check.t 15 | install: cpanm ExtUtils::PkgConfig Test::Text TAP::Harness 16 | script: perl -MTAP::Harness -e 'use utf8; my $harness = TAP::Harness->new( { verbosity => 0} ); die "FAIL" if $harness->runtests( "just_check.t" )->failed;' 17 | 18 | -------------------------------------------------------------------------------- /LICENCIA: -------------------------------------------------------------------------------- 1 | Licencia 2 | ==== 3 | 4 | This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introducción a JavaScript 2 | ======== 3 | 4 | [![Build Status](https://travis-ci.org/JJ/curso-js.svg?branch=master)](https://travis-ci.org/JJ/curso-js) 5 | 6 | Curso de 7 | [JavaScript cliente-servidor para el CEV-UGR](http://cevug.ugr.es/javascript). Cuarta edición en octubre de 2015, termina el 11 de diciembre. Si estás interesado en asistir al curso virtual, escríbenos o mantente informado en la página del curso en la web del [centro de enseñanzas virtuales de la UGR](http://cevug.ugr.es/javascript/). 8 | 9 | Ahora también disponible como [libro en Amazon](https://www.amazon.es/dp/B00HXL8QA0?tag=atalaya-21&camp=3634&creative=24822&linkCode=as4&creativeASIN=B00HXL8QA0&adid=1CR706WQ1340FXERHCDH&). 10 | 11 | ![Licencia cc-by-sa](http://es.creativecommons.org/blog/wp-content/uploads/2013/04/by-sa_petit.png) 12 | 13 | ## Instrucciones para generar 14 | 15 | El [directorio `utils`](utils/) incluye herramientas para su 16 | generación en diferentes formatos. 17 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | #Cosas que hacer 2 | 3 | * [X] Generar automáticamente diferentes formatos con pandoc 4 | * [ ] Añadir integración continua con corrección ortográfica. 5 | * [X] Dividir el texto en diferentes capítulos para más fácil corrección. 6 | * [ ] Terminar la conversión a Markdown desde HTML. 7 | * [ ] Corregir errores en el texto. 8 | * [ ] Añadir documentación. 9 | * [ ] Añadir jshints 10 | * [ ] Añadir Gruntfile 11 | -------------------------------------------------------------------------------- /code-es6/count-server.js: -------------------------------------------------------------------------------- 1 | /* jshint esversion: 6 */ 2 | 'use strict'; 3 | 4 | const fs = require('fs'), 5 | express = require('express'), 6 | app = express(); 7 | 8 | let contadores = [], 9 | portada = fs.readFileSync('sumar_formulario.html', 'utf8'); 10 | 11 | const getPortada = (req, res) => res.send(portada); 12 | 13 | const getPage = (req, res) => { 14 | let js = fs.readFileSync(req.params.page); 15 | res.contentType('text/javascript'); 16 | res.send(js); 17 | }; 18 | 19 | const putContador = (req, res) => { 20 | contadores[req.params.id] = 0; 21 | res.send('Creado contador ' + req.params.id); 22 | }; 23 | 24 | const postContador = (req, res) => { 25 | contadores[req.params.id]++; 26 | res.contentType('application/json'); 27 | res.send({resultado: contadores[req.params.id]}); 28 | console.log({post: contadores}); 29 | }; 30 | 31 | const getContador = (req, res) => { 32 | res.contentType('application/json'); 33 | res.send({ resultado: contadores[req.params.id]}); 34 | }; 35 | 36 | const getSuma = (req, res) => res.send({ 37 | resultado: contadores[req.params.id1] + contadores[req.params.id2] 38 | }); 39 | 40 | app.get('/', getPortada); 41 | app.get('/js/:page', getPage); 42 | app.put('/contador/:id', putContador); 43 | app.post('/contador/:id', postContador); 44 | app.get('/contador/:id', getContador); 45 | app.get('/suma/:id1/:id2', getSuma); 46 | 47 | app.listen(8080); 48 | console.log('Server running at http://127.0.0.1:8080/'); -------------------------------------------------------------------------------- /code-es6/express-count.js: -------------------------------------------------------------------------------- 1 | /* jshint esversion: 6 */ 2 | 'use strict'; 3 | 4 | const express = require('express'), 5 | app = express(), 6 | puerto = process.argv[2] ? process.argv[2] : 8080; 7 | 8 | let contadores = []; 9 | 10 | /* Funciones */ 11 | const getAll = (req, res) => res.send('Portada'); 12 | 13 | const putOne = (req, res) => { 14 | contadores[req.params.id] = 0; 15 | res.send({creado: req.params.id}); 16 | }; 17 | 18 | const getOne = (req, res) => res.send('{ ' + req.params.id + ': ' + contadores[req.params.id] + '}'); 19 | 20 | const postOne = (req, res) => { 21 | contadores[req.params.id]++; 22 | res.send('{ ' + req.params.id + ': ' + contadores[req.params.id] + '}'); 23 | }; 24 | 25 | /* Rutas */ 26 | app.get('/', getAll); 27 | app.put('/contador/:id', putOne); 28 | app.get('/contador/:id', getOne); 29 | app.post('/contador/:id', postOne); 30 | 31 | /* Puesta en marcha del servidor */ 32 | app.listen(puerto); 33 | console.log('Server running at http://127.0.0.1:' + puerto + '/'); -------------------------------------------------------------------------------- /code-es6/github-get-largo.js: -------------------------------------------------------------------------------- 1 | /* jshint esversion: 6 */ 2 | 3 | const https = require('https'), 4 | state = process.argv[2] ? process.argv[2] : 'open', 5 | options = { 6 | host: 'api.github.com', 7 | path: 'https://api.github.com/repos/jj/curso-js/issues?state=' + state, 8 | method: 'GET', 9 | headers: {'user-agent': 'PruebaNode'} 10 | }; 11 | 12 | 13 | const parseFunction = (res) => { 14 | let datos_JSON_acc = ''; 15 | 16 | res.setEncoding('utf8'); 17 | res.on('data', (datos_JSON) => datos_JSON_acc += datos_JSON); 18 | res.on('end', () => { 19 | let datos = JSON.parse(datos_JSON_acc); 20 | if (Array.isArray(datos)) { 21 | for (let i = 0, len = datos.length; i < len; i++) { 22 | console.log('Issue: ' + datos[i].title + '\nUser: ' + datos[i].user.login + '\n'); 23 | } 24 | } else { 25 | console.log('Issue: ' + datos.title + '\nUser: ' + datos.user.login + '\n'); 26 | } 27 | }); 28 | }; 29 | 30 | const req = https.get(options, parseFunction); 31 | 32 | req.end(); 33 | -------------------------------------------------------------------------------- /code-es6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code-es6", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "express": "^4.14.1", 6 | "fs": "0.0.1-security", 7 | "http": "0.0.0", 8 | "https": "^1.0.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /code-es6/servidor-var.js: -------------------------------------------------------------------------------- 1 | /* jshint esversion: 6 */ 2 | 3 | const http = require('http'); 4 | 5 | const createServer = (req, res) => { 6 | res.writeHead(200, {'Content-Type': 'text/plain'}); 7 | res.end('Ahí estamos ' + req.url); 8 | }; 9 | 10 | http.createServer(createServer).listen(8081, '127.0.0.1'); 11 | 12 | console.log('Servidor ejecutándose en http://127.0.0.1:8081/'); -------------------------------------------------------------------------------- /code-es6/servidor.js: -------------------------------------------------------------------------------- 1 | /* jshint esversion: 6 */ 2 | 3 | const http = require('http'); 4 | 5 | const createServer = (req, res) => { 6 | res.writeHead(200, {'Content-Type': 'text/plain'}); 7 | res.end('Ahí estamos\n'); 8 | }; 9 | 10 | http.createServer(createServer).listen(8080, '127.0.0.1'); 11 | 12 | console.log('Servidor ejecutándose en http://127.0.0.1:8080/'); -------------------------------------------------------------------------------- /code-es6/sumar_formulario.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sumador usando Ajax 5 | 6 | 7 | 8 | 9 |

Prueba AJAX

10 | 11 |

Inserta el nombre del contador para mostrar su valor.

12 | 13 |

Contador:

14 |
  
15 | 16 |
17 |
Juan J. Merelo
18 | 19 | Last modified: Sun May 12 18:06:21 CEST 2013 20 | 21 | 22 | -------------------------------------------------------------------------------- /code/Nuevo_partido.js: -------------------------------------------------------------------------------- 1 | // Definición de la clase Partido 2 | function Nuevo_partido(local,visitante, resultado) { 3 | this.local = local; 4 | this.visitante=visitante; 5 | this.resultado=resultado; 6 | this.setResultado = setResultado; 7 | this.toString = toString; 8 | this.set_to_string = set_to_string; 9 | this.impresor = _toString; 10 | } 11 | 12 | function setResultado( esteResultado ) { 13 | if ( esteResultado == '1' || esteResultado=='x' || esteResultado=='2' ) 14 | this.resultado = esteResultado; 15 | } 16 | 17 | function toString() { 18 | return this.impresor(this.local, this.visitante, this.resultado); 19 | } 20 | 21 | function _toString( local, visitante ) { 22 | return ": " + this.local + " - " + this.visitante + " = "+ this.resultado; 23 | } 24 | 25 | function set_to_string ( impresor ) { 26 | this.impresor = impresor; 27 | } -------------------------------------------------------------------------------- /code/Partido.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JJ/curso-js/8d3ea9afe28aa112bd92f3766ecc9b2bfde3ff2a/code/Partido.js -------------------------------------------------------------------------------- /code/Quiniela.js: -------------------------------------------------------------------------------- 1 | // Definición de la clase Partido 2 | function Partido(_local,_visitante) { 3 | this.local = _local; 4 | this.visitante=_visitante; 5 | this.resultado=null; 6 | } 7 | 8 | var equipos= new Array('Madrid', 'Barça', 'Atleti', 'Geta', 'Betis', 'Depor', 'Sevilla', 'Graná'); 9 | 10 | var midsize = equipos.length/2; 11 | var quiniela = new Array( midsize ); 12 | for ( i=0; i < midsize ; i++ ) { 13 | var equipo1 = equipos.splice(Math.floor( equipos.length*Math.random()) , 1); 14 | var equipo2 = equipos.splice(Math.floor( equipos.length*Math.random()), 1); 15 | quiniela[i] = new Partido( equipo1, equipo2 ); 16 | } 17 | 18 | for ( i in quiniela ) { 19 | print( "Partido " + (parseInt(i)+1)+": " + quiniela[i].local + " - " + quiniela[i].visitante); 20 | } 21 | -------------------------------------------------------------------------------- /code/Resultado.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JJ/curso-js/8d3ea9afe28aa112bd92f3766ecc9b2bfde3ff2a/code/Resultado.js -------------------------------------------------------------------------------- /code/Resultados.js: -------------------------------------------------------------------------------- 1 | // Lee los resultados de un fichero y los devuelve como array. 2 | function lee_resultados( file_name ) { 3 | var FileReader = java.io.FileReader; 4 | var BufferedReader =java.io.BufferedReader; 5 | var f = new FileReader(file_name); 6 | var br = new BufferedReader( f ); 7 | var resultados= new Array; 8 | var line = new String; 9 | if ( !resultados[resultado[0]] ) { 10 | resultados[resultado[0]]=0; 11 | } 12 | if ( !resultados[resultado[1]] ) { 13 | resultados[resultado[1]]=0; 14 | } 15 | while ((line = br.readLine()) != null) { 16 | var estaLinea = new String( line ); 17 | var resultado = estaLinea.split(" "); 18 | switch (resultado[2]) { 19 | case '1': 20 | resultados[resultado[0]]+=3; 21 | break; 22 | case 'x': 23 | resultados[resultado[0]]+=1; 24 | resultados[resultado[1]]+=1; 25 | break; 26 | default: 27 | resultados[resultado[1]]+=3; 28 | break 29 | } 30 | } 31 | 32 | return resultados; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /code/Un_Partido.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JJ/curso-js/8d3ea9afe28aa112bd92f3766ecc9b2bfde3ff2a/code/Un_Partido.js -------------------------------------------------------------------------------- /code/aap-nav.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name AAP-Nav 3 | // @namespace http://geneura.org/projects/greasemonkey 4 | // @description Navegación por las secciones de AAP 5 | // @include http://geneura.ugr.es/~jmerelo/asignaturas/* 6 | // ==/UserScript== 7 | 8 | GM_log('Entrando en AAP-Nav'); 9 | var h2 = document.getElementsByTagName('h2'); 10 | var a_nodes = new Array; 11 | var anchors = new Array; 12 | for ( var secs = 0; secs < h2.length; secs ++ ) { 13 | var thisA = h2[secs].getElementsByTagName('a'); 14 | a_nodes[secs] = thisA[0]; 15 | anchors[secs] = thisA[0].getAttribute('name'); 16 | GM_log('Anchor ' + secs + " " + anchors[secs]); 17 | } 18 | 19 | for ( var secs = 0; secs < h2.length; secs ++ ) { 20 | var span = document.createElement('span'); 21 | span.setAttribute('style','background:lightblue'); 22 | if ( secs > 0 ) { 23 | var ahref = document.createElement('a'); 24 | ahref.setAttribute('href','#'+anchors[secs-1]); 25 | var txt=document.createTextNode('^'); 26 | ahref.appendChild(txt); 27 | span.appendChild(ahref); 28 | } 29 | if ( secs < h2.length -1 ) { 30 | span.appendChild(document.createTextNode(' | ')); 31 | var ahref = document.createElement('a'); 32 | ahref.setAttribute('href','#'+anchors[secs+1]); 33 | var txt=document.createTextNode('v'); 34 | ahref.appendChild(txt); 35 | span.appendChild(ahref); 36 | } 37 | a_nodes[secs].parentNode.insertBefore(span,a_nodes[secs]); 38 | } 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /code/bg-1.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Blogalia 3 | // @namespace http://geneura.org/projects/greasemonkey 4 | // @description Cambia cosas en la portada de blogalia 5 | // @include http://www.blogalia.com/ 6 | // @include http://blogalia.com/ 7 | // ==/UserScript== 8 | 9 | GM_log('Aquí estoy'); 10 | var table = document.getElementById('historias'); 11 | GM_log('table ' + table ); 12 | //var blogs = document.evaluate("tr", 13 | // document.getElementById('historias'), 14 | // null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 15 | var blogs = table.getElementsByTagName('tr'); 16 | GM_log('blogs.length ' + blogs.length ); 17 | //var info; 18 | //for ( var i = 0; i < blogs.snapshotLength; i ++ ) { 19 | // GM_log(blogs.snapshotItem(i).textContent); 20 | //} 21 | 22 | for ( var row = 0; row < blogs.length; row ++ ) { 23 | var columns = blogs[row].getElementsByTagName('td'); 24 | // for ( var column = 0; column < columns.length; column++ ) { 25 | // GM_log(row + " - " + column + " - " + columns[column].textContent); 26 | // } 27 | columns[0].style.background='yellow'; 28 | } 29 | -------------------------------------------------------------------------------- /code/bg-2.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Blogalia 3 | // @namespace http://geneura.org/projects/greasemonkey 4 | // @description Cambia cosas en la portada de blogalia 5 | // @include http://www.blogalia.com/ 6 | // @include http://blogalia.com/ 7 | // ==/UserScript== 8 | 9 | GM_log('Aquí estoy'); 10 | var table = document.getElementById('historias'); 11 | GM_log('table ' + table ); 12 | //var blogs = document.evaluate("tr", 13 | // document.getElementById('historias'), 14 | // null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 15 | var blogs = table.getElementsByTagName('tr'); 16 | GM_log('blogs.length ' + blogs.length ); 17 | //var info; 18 | //for ( var i = 0; i < blogs.snapshotLength; i ++ ) { 19 | // GM_log(blogs.snapshotItem(i).textContent); 20 | //} 21 | 22 | for ( var row = 0; row < blogs.length; row ++ ) { 23 | var columns = blogs[row].getElementsByTagName('td'); 24 | // for ( var column = 0; column < columns.length; column++ ) { 25 | // GM_log(row + " - " + column + " - " + columns[column].textContent); 26 | // } 27 | var thisA = columns[0].getElementsByTagName('a'); 28 | var span = document.createElement('span'); 29 | span.style='background:blue'; 30 | var txt = document.createTextNode(' '); 31 | span.appendChild(txt); 32 | thisA.parentNode.insertBefore(span, thisA); 33 | } 34 | -------------------------------------------------------------------------------- /code/bg-2.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Blogalia 3 | // @namespace http://geneura.org/projects/greasemonkey 4 | // @description Cambia cosas en la portada de blogalia 5 | // @include http://www.blogalia.com/ 6 | // @include http://blogalia.com/ 7 | // ==/UserScript== 8 | 9 | 10 | var table = document.getElementById('historias'); 11 | var blogs = table.getElementsByTagName('tr'); 12 | 13 | for ( var row = 0; row < blogs.length; row ++ ) { 14 | var columns = blogs[row].getElementsByTagName('td'); 15 | var thisA = columns[0].getElementsByTagName('a'); 16 | var span = document.createElement('span'); 17 | span.setAttribute('style','background:blue'); 18 | var txt = document.createTextNode('*'); 19 | span.appendChild(txt); 20 | thisA[0].parentNode.insertBefore(span, thisA[0]); 21 | } 22 | -------------------------------------------------------------------------------- /code/bg-3.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Blogalia 3 | // @namespace http://geneura.org/projects/greasemonkey 4 | // @description Cambia cosas en la portada de blogalia 5 | // @include http://www.blogalia.com/ 6 | // @include http://blogalia.com/ 7 | // ==/UserScript== 8 | 9 | 10 | var table = document.getElementById('historias'); 11 | var blogs = table.getElementsByTagName('tr'); 12 | var request; 13 | 14 | request = new XMLHttpRequest(); 15 | 16 | request.open('GET', 'http://geneura.ugr.es/~jmerelo/atalaya/chismes/comentarios_xml.cgi', true); 17 | request.onreadystatechange= putComentarios ; 18 | request.send(null); 19 | var comentarios; 20 | 21 | function putComentarios(){ 22 | if ( request.readyState == 4 ) { 23 | if ( request.status == 200 ) { 24 | var doc = request.responseXML; 25 | var root=doc.documentElement; 26 | var html="