1

Detectar cuando se deja de escribir en un input o textArea

¡Hola soy Juan!

Mientras estaba trabajando en un proyecto ‘secreto’ 😏 me surgió un problemilla y es que necesitaba detectar cuando el usuario dejaba de escribir en un input para poder hacer una petición ajax, esto con el fin de o hacer la petición cada vez que presionará una tecla, entonces lo primero que hice fue buscar un código que quizá ya habrían hecho para esto, hallé una librería pero no quería usar una Librería para ello, puesto pensé que no sería algo extraordinario, luego encontré un código pero se usaba un setInterval el cual lo implementé y no satisfacía mi necesidad, así que lo modifiqué un poco en esta ocasión usando mejor un setTimeout el cual a la final, funcionó de maravilla dejo el código por si te interesa o lo necesitas.

Si tienes una forma mucho más sencilla y/o eficiente de hacerlo o si tienes una mejora para el código estaré encantado de leer tu FeedBack.

<input type="text" id="comment" />
let $comment = document.getElementById("comment")
let timeout

//El evento lo puedes reemplazar con keyup, keypress y el tiempo a tu necesidad
$comment.addEventListener('keydown', () => {
  clearTimeout(timeout)
  timeout = setTimeout(() => {
    console.log('Has dejado de escribir en el input')
    clearTimeout(timeout)
  },1000)
})
Escribe tu comentario
+ 2
Ordenar por:
1
un año

Hola Juan, le agregué unas pequeñas mejoras al código.

  1. Validaciones de espacios vacíos (no queremos que sature al servidor con valores no válidos). if (e.target.value.trim() === "") return;

  2. En este escenario timeout funciona mejor con el evento “keyup” que es cuando se suelta la tecla.

  3. Como buena práctica, cuando agregues un eventListener evita usar funciones anónimas porque en ocasiones tienes que eliminar el elemento dinámicamente, y si usas la función $comment.RemoveEventListener("keyup", listener?) El parametro listener es la función, pero como es una funcion anonima no tiene una referencia en memoria, en tu primera versión no podrias removerlo.

<inputtype="text"id="comment" /><script>let timeout;
    const $input_text = document.querySelector("#comment");
    
    $input_text.addEventListener("keyup", callApi);

    functioncallApi(e) {
			// Si es vacio entonces termina la ejecucionif (e.target.value.trim() === "") return;
      	console.log({ value: e.target.value });
      	clearTimeout(timeout);
     		timeout = setTimeout(() => {
        	console.log(`request to API '${e.target.value}'`);
        	clearTimeout(timeout);
      	}, 1000);
    }
 </script>
", "created_at": "2024-02-09T17:26:35.679009Z", "deep": 0, "n_responses": 0, "n_stars": 1, "parent_id": null, "ai_generated": false}, "4741502": {"id": 4741502, "object_id": "2575", "object_type": "contribution", "author_id": 4795603, "comments": [], "content": "

Excelente aporte, muchas gracias

", "markdown_content": "Excelente aporte, muchas gracias", "created_at": "2023-04-29T18:26:06.548141Z", "deep": 0, "n_responses": 0, "n_stars": 1, "parent_id": null, "ai_generated": false}, "4122433": {"id": 4122433, "object_id": "2575", "object_type": "contribution", "author_id": 2595888, "comments": [], "content": "

Muy bien!

", "markdown_content": "Muy bien!", "created_at": "2022-09-29T08:00:59.453300Z", "deep": 0, "n_responses": 0, "n_stars": 1, "parent_id": null, "ai_generated": false}}; window.course = {"name": "Fundamentos de JavaScript 2017", "slug": "fundamentos-javascript-2017", "id": 1099, "badge": "https://static.platzi.com/media/achievements/badge-Fundamentos-js.png", "paid": true}; window.career = {"name": "Apps Multiplataforma", "color": "#5fa400", "url": "/learning-path/multiplataforma/"}; window.firstComments = [5075875, 4741502, 4122433]; window.stars = {"comments": [], "contribution": [], "related_posts": []}; window.messages = {"discussion": {"responsesTo": "Tutoriales de"}, "popups": {"login": {"welcome": "Bienvenido a Platzi", "loginFacebook": "Ingresa con facebook", "loginTwitter": "Ingresa con Twitter", "loginMail": "\u00bfIngresas con email?", "haveAccount": "\u00bfA\u00fan no tienes cuenta?", "signup": "Reg\u00edstrate aqu\u00ed", "privacy": {"part1": "Valoramos tu", "part2": "privacidad", "part3": "como si fuera nuestra"}, "terms": {"part1": "Ante cualquier duda, nuestros", "part2": "Terminos de servicio"}}, "pay": {"buyPlan": "Comprar Plan", "monthly": {"label": "En 12 pagos sin intereses"}}}, "response": {"time": "hace", "respond": "Escribe tu respuesta", "hideResponses": "Ocultar respuestas", "numberOfResponses": "{number} respuestas", "responseOf": "{number} respuesta", "delete": "Eliminar"}, "form": {"placeholder": "Deja tu comentario", "editor": {"placeholder": "Escribe tu pregunta", "edit": "Editar", "preview": "Vista previa", "expand": "Expandir", "contract": "Contraer", "bold": "Negrita", "italic": "Cursiva", "underline": "Subrayado", "heading": "Encabezado", "code": "Insertar c\u00f3digo", "quote": "Cita", "link": "Enlace", "unorderedList": "Lista desordenada", "orderedList": "Lista ordenada", "image": "Imagen", "youtube": "Youtube", "uploading": "Subiendo imagen"}, "buttons": {"send": "Enviar", "sending": "Enviando", "cancel": "Cancelar"}, "helpbar": {"markdown": "Markdown", "preview": "Vista previa"}, "bottom": {"title": "T\u00edtulo"}}, "access.now": "ver clase", "post.related": "Entradas relacionadas", "start.now": "ver clase sin costo", "banner": {"message": "Estas respuestas son parte del {course}.
Accede a todos los cursos desde {currency} al a\u00f1o", "button": "Suscr\u00edbete"}, "labels": {"question": "Pregunta"}, "bestAnswer": "Mejor respuesta", "comments": {"reply": "Responder", "replyDisabled": "Ocultar", "delete": "Eliminar", "bestAnswer": "Mejor respuesta", "getMore": "Ver todas las respuestas", "points": "Puntos", "new": "Nuevas", "top": "Top", "orderBy": "Ordenar por:", "viewMore": "Ver m\u00e1s"}, "modal.delete.title": "\u00bfQuieres eliminar este Post?", "modal.delete.sub": "Eliminar Blogspost", "modal.delete.error": "Ha ocurrido un error :(", "modal.delete.loading": "Borrando Post...", "modal.delete.yes": "Si, eliminar", "modal.delete.no": "No", "login.fb": "Ingresa con facebook", "login.social": "Con tus redes sociales", "login.tw": "Ingresa con twitter", "author.posts": "Todas sus entradas", "editor.submit.b": "Suma tu comentario", "editor.submit.a": "Sin timidez", "editor.submit.c": "Suma tu comentario", "form.editor.isQuestion": "\u00bfTu comentario es una pregunta?", "delete": "Eliminar", "edit": "Editar", "posts.related": "Entradas relacionadas", "login.email.title": "Con tu Email", "login.email": "Correo electr\u00f3nico", "login.password.forgot": "\u00bfOlvidaste tu contrase\u00f1a?", "login.account": "\u00bfA\u00fan no tienes cuenta? Reg\u00edstrate aqu\u00ed", "LoginSocial-facebook-login": "Iniciar sesi\u00f3n con Facebook", "LoginSocial-twitter-login": "Iniciar sesi\u00f3n con Twitter", "LoginSocial-google-login": "Iniciar sesi\u00f3n con Google", "login_email": "Tu email", "login_password": "Tu contrase\u00f1a", "LoginWithEmail-login": "Iniciar sesi\u00f3n", "LoginWithEmail-lostpassword": "\u00bfOlvidaste tu contrase\u00f1a?", "AccountFooter-title-register": "\u00bfA\u00fan no tienes cuenta en Platzi?", "AccountFooter-register": "Crear cuenta", "AccountFooter-login": "Inicia tu sesi\u00f3n", "AccountFooter-title-login ": "\u00bfYa tienes una cuenta?", "RegisterButton-email": "Reg\u00edstrate con tu Email", "LoginSocial-twitter-register": "Reg\u00edstrate con Twitter", "LoginSocial-facebook-register": " Reg\u00edstrate con Facebook", "LoginSocial-google-register": " Reg\u00edstrate con Google", "write_your_comment": "Escribe tu comentario", "question_send": "Tu pregunta fue enviada al ", "discussion_system": "sistema de discusiones", "ShareButtons_share": "Comparte en:", "unlogged_course_title": "Toma sin costo la primera clase del {title}", "ScrollModal_general_error": "Ha ocurrido un error, vuelve a intentarlo", "ScrollModal_email_error": "Este correo no es v\u00e1lido.", "ScrollModal_title": "D\u00e9janos tu correo electr\u00f3nico y recibe m\u00e1s contenido como este", "ScrollModal_placeholder": "Ingresa tu correo", "ScrollModal_cta": "Continuar"}; window.userId = 'None'; window.userEmail = ''; window.isOrganizer = false; window.isAuthor = false; window.isContribution = true; window.avatar = 'https://static.platzi.com/static/website/v2/images/avatar_default.7516253fc982.png'; window.userType = 'unlogged'; window.breadcrumb = [{"label": "Inicio", "url": "/"}, {"label": "Fundamentos de JavaScript 2017", "url": "/cursos/fundamentos-javascript-2017/"}]; window.isBlog = false; window.isProject = false; window.projectCourse = false; window.isFavorite = ""; window.canFavorite = false window.features = {"favorites_enabled": true}; window.contentType = "contribution" window.objectData = {"objectId": 2575, "objectType": "contribution"}; window.comment = { list: window.firstComments, data: window.comments, likes: window.stars.comments, highlighted: null, pagination: { current: 1, total: Math.ceil(window.discussion.n_responses/100), }, }; window.testAb = ''; window.diplomado = { date: new Date(''), is_active: false, }; window.relatedCourse = {} window.relatedCategory = window.relatedPosts = [{"pk": 2652, "draft": false, "title": "Animaciones en JS", "created_at": "2018-08-02T01:34:16.036902Z", "slug": "animaciones-en-js", "active": true, "type": "text", "subtype": "html", "content": "Me gust\u00f3 mucho lo que aprend\u00ed en este curso, las Bases de JavaScript, me gustar\u00eda que ense\u00f1aran a hacer animaciones aparte de setTimeout y s", "score": 8870, "course_id": 1099, "author_id": 31474, "cover_image": null, "og_image": null, "stars_count": 8, "responses_count": 0, "platzi_old_id": null, "related_course_id": null, "related_career_id": null, "related_learning_path_id": null, "pinned_post": false, "organization_id": null, "seo_title": "", "seo_description": "", "updated_at": "2023-11-20T07:39:20.323396Z", "category_id": null, "akismet_spam": false, "author_data": {"username": "Zero_System", "avatar": "https://static.platzi.com/media/avatars/avatars/Plastilem_93508bb7-0a08-4076-b205-8ded271eca84.jpg"}, "url": "/tutoriales/1099-fundamentos-javascript-2017/2652-animaciones-en-js/", "color": "#efdb4f", "cover_thumbs": ""}, {"pk": 2625, "draft": false, "title": "**Explicacion sobre Funciones Flecha \u2013 _Arrow Functions_**", "created_at": "2018-07-30T13:39:59.143251Z", "slug": "explicacion-sobre-funciones-flecha-_arrow-functions", "active": true, "type": "text", "subtype": "html", "content": "Este es mi aporte para intentar sacar el mejor provecho de la arrow function.\n\nEste tipo de funciones tiene una sintaxis variada que depende", "score": 8865, "course_id": 1099, "author_id": 504813, "cover_image": null, "og_image": null, "stars_count": 3, "responses_count": 2, "platzi_old_id": null, "related_course_id": null, "related_career_id": null, "related_learning_path_id": null, "pinned_post": false, "organization_id": null, "seo_title": "", "seo_description": "", "updated_at": "2025-04-14T04:54:38.036671Z", "category_id": null, "akismet_spam": false, "author_data": {"username": "adrian-gonzalez", "avatar": "https://static.platzi.com/media/avatars/adrian-gonzalez_1f28a71f-f10f-4c77-82eb-daf72d5ca004"}, "url": "/tutoriales/1099-fundamentos-javascript-2017/2625-explicacion-sobre-funciones-flecha-_arrow-functions/", "color": "#efdb4f", "cover_thumbs": ""}, {"pk": 2628, "draft": false, "title": "Document Object Model (DOM)", "created_at": "2018-07-30T18:27:59.185405Z", "slug": "document-object-model-dom", "active": true, "type": "text", "subtype": "html", "content": "Document Object Model (DOM)\nEl objeto document hace referencia a determinadas caracter\u00edsticas de la p\u00e1gina, como son su color de fondo (bgCo", "score": 8865, "course_id": 1099, "author_id": 504813, "cover_image": null, "og_image": null, "stars_count": 3, "responses_count": 0, "platzi_old_id": null, "related_course_id": null, "related_career_id": null, "related_learning_path_id": null, "pinned_post": false, "organization_id": null, "seo_title": "", "seo_description": "", "updated_at": "2025-03-04T03:06:11.724735Z", "category_id": null, "akismet_spam": false, "author_data": {"username": "adrian-gonzalez", "avatar": "https://static.platzi.com/media/avatars/adrian-gonzalez_1f28a71f-f10f-4c77-82eb-daf72d5ca004"}, "url": "/tutoriales/1099-fundamentos-javascript-2017/2628-document-object-model-dom/", "color": "#efdb4f", "cover_thumbs": ""}, {"pk": 2626, "draft": false, "title": "Hoisting", "created_at": "2018-07-30T14:03:24.205016Z", "slug": "hoisting", "active": true, "type": "text", "subtype": "html", "content": "Para entender un poco del motor de Javascript.\n\nEn la mayor\u00eda de los lenguajes de programaci\u00f3n, el \u00e1mbito / alcance de una variable est\u00e1 en ", "score": 8865, "course_id": 1099, "author_id": 504813, "cover_image": null, "og_image": null, "stars_count": 4, "responses_count": 20, "platzi_old_id": null, "related_course_id": null, "related_career_id": null, "related_learning_path_id": null, "pinned_post": false, "organization_id": null, "seo_title": "", "seo_description": "", "updated_at": "2024-06-27T17:19:16.721600Z", "category_id": null, "akismet_spam": false, "author_data": {"username": "adrian-gonzalez", "avatar": "https://static.platzi.com/media/avatars/adrian-gonzalez_1f28a71f-f10f-4c77-82eb-daf72d5ca004"}, "url": "/tutoriales/1099-fundamentos-javascript-2017/2626-hoisting/", "color": "#efdb4f", "cover_thumbs": ""}] window.projectsCategories = [ { title: 'Proyectos destacados', color: 'red', url: 'https:platzi.com', projects: [ { name: 'Platzi Music', url: 'http://platzi.com/hola', level: 'Avanzado', stars: 10, comments: 20, image: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', description: 'Aplicación construida en VueJS con la que puedes armar tus listas de reproducción y hacer búsquedas', author: { avatar: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', username: 'unmalnick' } }, { name: 'Platzi Music', url: 'http://platzi.com/hola', level: 'Avanzado', stars: 10, comments: 20, image: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', description: 'Aplicación construida en VueJS con la que puedes armar tus listas de reproducción y hacer búsquedas', author: { avatar: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', username: 'unmalnick' } }, { name: 'Platzi Music', url: 'http://platzi.com/hola', level: 'Avanzado', stars: 10, comments: 20, image: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', description: 'Aplicación construida en VueJS con la que puedes armar tus listas de reproducción y hacer búsquedas', author: { avatar: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', username: 'unmalnick' } }, { name: 'Platzi Music', url: 'http://platzi.com/hola', level: 'Avanzado', stars: 10, comments: 20, image: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', description: 'Aplicación construida en VueJS con la que puedes armar tus listas de reproducción y hacer búsquedas', author: { avatar: 'http://www.clubit.tv/wp-content/uploads/2017/08/pokemon.jpg', username: 'unmalnick' } }, ] } ] window.currency = { flag: '', price: '', fullPrice: '', } window.preConfDate = new Date('') window.conf = { confEnd: new Date(''), isConfActive: false , }; window.limitDate = new Date(''); window.limitedPromo = { name: '', token: '', }; window.endBarDate = new Date(''); window.barState = ''; window.contactInfo = { hasSubscription: false, isAuthenticated: false, country: "united-states", flag: "https://static.platzi.com/static/images/languajes/united-states.jpg", isOrganizer: false, lang: "es", i18n: {'contactus_title': '¿Tienes dudas o quieres comunicarte con nosotros?', 'contactus_subtitle': 'Elige el medio que más te convenga, te sugerimos ', 'write': 'Escríbenos', 'dm': 'Mensaje Directo', 'telephone': 'Teléfono', 'acceptTerms': 'Nunca pares de aprender sobre la seguridad de tus datos', 'agree': 'Aquí puedes ver nuestros {terms} y actualizaciones de nuestras {privacy}', 'terms': 'Términos de Uso', 'privacy': 'políticas de privacidad', 'accept': 'Términos de Uso', 'planExpert': 'Plan Expert', 'planExpertText': 'Desarrolla tus habilidades en programación, diseño, producción audiovisual, marketing y muchas más. Mide tu progreso y recibe certificados con tu nombre a finalizar cada curso.'}, enabled: true, accepted_gdpr: false, userId: '0', organizationId: '1', faq: [{'title': 'Quiero contactar directamente a Platzi', 'cta': 'https://platzi.com/faq/#contacto'}, {'title': '¿Cómo funcionan los cursos? ¿Debo seguir un horario?', 'cta': 'https://platzi.com/faq/#como-funcionan-cursos'}, {'title': '¿Qué necesito para tomar los cursos?', 'cta': 'https://platzi.com/faq/#que-necesito'}, {'title': '¿Qué medios de pago aceptan?', 'cta': 'https://platzi.com/faq/#medios-pago'}, {'title': 'Contactarme por mail', 'cta': 'mailto:[email protected]'}], faq_title: '¿Tienes alguna duda o quieres comunicarte con nosotros?', }