diff --git a/public/js/main.js b/public/js/main.js index fe434d7..0d97e33 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,3 +1,13 @@ +const scrollBtn = document.getElementById('contributors') +const targetScroll = document.getElementById('contributors-title') +const elemRect = targetScroll.getBoundingClientRect() +scrollBtn.addEventListener("click", function () { + window.scrollTo({ + top: elemRect.top, + left: 0, + }); +}); + const btn = document.getElementById('keyword-btn'); btn.addEventListener('click', getMatches); @@ -30,14 +40,20 @@ function renderMatches(matches) { list.innerHTML = ''; // For every match found, render the objects to the DOM in JSON format - matches.forEach(match => { - const li = document.createElement('li'); + if(matches.length > 0) { + matches.forEach(match => { + const li = document.createElement('li'); - // Create an element that looks like a JSON object for every match - li.innerHTML = ` -
{

name: '${match.name}',
url: '${match.url}',
keywords: [${match.keywords.map(keyword => `'${keyword}'`).join(", ")}]
},
- `; + // Create an element that looks like a JSON object for every match + li.innerHTML = ` +
{

name: '${match.name}',
url: '${match.url}',
keywords: [${match.keywords.map(keyword => `'${keyword}'`).join(", ")}]
},
+ `; + list.appendChild(li); + }); + } else { + const li = document.createElement('li'); + li.innerText = 'No matches were found.'; list.appendChild(li); - }); + } } \ No newline at end of file diff --git a/resources.js b/resources.js index 507a1c1..50666f5 100644 --- a/resources.js +++ b/resources.js @@ -79,6 +79,192 @@ const resources = [ url: 'https://javascript.info/object', keywords: ['javascript', 'objects'] }, + { + name: 'Crypto Zombies', + url: "https://cryptozombies.io", + keywords: ["crypto", "web3", "blockchain"] + }, + { + name: 'How to make your first pull request on GitHub', + url: "https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/", + keywords: ["open source", "git"] + }, + { + name: 'CORS Proxy', + url: 'https://codetabs.com/cors-proxy/cors-proxy.html', + keywords: ['cors', 'proxy', 'api', 'errors'] + }, + { + name: 'How to write good commit messages', + url: 'https://www.freecodecamp.org/news/writing-good-commit-messages-a-practical-guide/', + keywords: ['git', 'commit', 'version control', 'command line'] + }, + { + name: 'Grind 75 questions', + url: 'https://www.techinterviewhandbook.org/grind75', + keywords: ['interview', 'job search', 'coding challenges', 'leet code'] + }, + { + name: 'Font Awesome', + url: 'https://faicons.com/', + keywords: ['icons', 'frontend'] + }, + { + name: 'Frontend Project README template', + url: 'https://github.com/alecortega/portfolio-template', + keywords: ['markdown', 'frontend', 'documentation'] + }, + { + name: 'CSS Diner', + url: 'https://flukeout.github.io/', + keywords: ['css'] + }, + { + name: 'Flexbox Froggy', + url: 'https://flexboxfroggy.com/', + keywords: ['css', 'flexbox'] + }, + { + name: 'Learn Git Branching', + url: 'https://learngitbranching.js.org/', + keywords: ['git', 'version control'] + }, + { + name: 'What the Flexbox', + url: 'https://flexbox.io/', + keywords: ['css', 'flexbox'] + }, + { + name: 'Code Driven Animation Editor', + url: 'https://www.timelinecss.io/', + keywords: ['css animations', 'css', 'animations', 'editor', 'visuals'] + }, + { + name: 'Simple Icons', + url: 'https://simpleicons.org', + keywords: ['free', 'svg icons', 'svg', 'icons', 'popular brands'] + }, + { + name: 'JavaScript Visualizer 9000', + url: 'https://www.jsv9000.app', + keywords: ['javascript', 'call stack', 'event loop', 'microtask queue', 'task queue'] + }, + { + name: 'unDraw', + url: 'https://undraw.co', + keywords: ['open-source illustrations', 'svg', 'images', 'design', 'graphics', 'art', 'vectors', 'minimal', 'free', 'modern', 'png', 'interface', 'open-source'] + }, + { + name: 'DevDocs', + url: 'https://devdocs.io', + keywords: ['api documentation', 'free', 'open-source', 'developer tools', 'interface', 'offline', 'css', 'html', 'http', 'javascript', 'web apis', 'angular', 'angularjs', 'ansible', 'apache http server', 'apache pig', 'async', 'babel', 'backbone.js', 'bash', 'bluebird', 'bootstrap', 'bottle', 'bower', 'c', 'c++', 'cakephp', 'chai', 'chef', 'clojure', 'cmake', 'codeception', 'codeceptjs', 'codeigniter', 'coffeescript', 'composer', 'cordova', 'crystal', 'cypress', 'd', 'd3.js', 'dart', 'deno', 'django', 'django rest framework', 'docker', 'dojo', 'drupal', 'eigen3', 'electron', 'elisp', 'elixir', 'ember.js', 'enzyme', 'erlang', 'esbuild', 'eslint', 'express', 'falcon', 'fish', 'flask', 'flow', 'gcc', 'git', 'gnu fortran', 'gnu make', 'gnucobol', 'gnuplot', 'go', 'godot', 'graphite', 'groovy', 'grunt', 'gtk', 'handlebars', 'haproxy', 'haskell', 'haxe', 'homebrew', 'i3', 'immutable.js', 'influxdata', 'jasmine', 'jekyll', 'jest', 'jinja', 'jq', 'jquery', 'jquery mobile', 'jquery ui', 'jsdoc', 'julia', 'knockout.js', 'koa', 'kotlin', 'kubectl', 'kubernetes', 'laravel', 'latex', 'leaflet', 'less', 'liquid', 'lodash', 'lua', 'love', 'mariadb', 'marionette.js', 'markdown', 'matplotlib', 'meteor', 'mocha', 'modernizr', 'moment.js', 'mongoose', 'nginx', 'nginx lua module', 'nim', 'nix', 'node.js', 'nokogiri', 'npm', 'numpy', 'ocaml', 'octave', 'openjdk', 'opentsdb', 'padrino', 'pandas', 'perl', 'phalcon', 'phaser', 'phoenix', 'php', 'phpunit', 'pointcloudlibrary', 'pony', 'postgresql', 'prettier', 'pug', 'puppeteer', 'pygame', 'python', 'pytorch', 'q', 'qt', 'r', 'ramda', 'react', 'reactbootstrap', 'react native', 'react router', 'reactivex', 'redis', 'redux', 'relay', 'requirejs', 'rethinkdb', 'ruby', 'ruby minitest', 'ruby on rails', 'rust', 'rxjs', 'saltstack', 'sass', 'scala', 'scikit-image', 'scikit-learn', 'sequelize', 'sinon.js', 'socket.io', 'spring boot', 'sqlite', 'statsmodels', 'support tables', 'svg', 'symfony', 'tailwind css', 'tcl tk', 'tensorflow', 'tensorflow c++', 'terraform', 'trio', 'twig', 'typescript', 'underscore.js', 'vagrant', 'vite', 'vue router', 'vue.js', 'vuex', 'vulkan', 'web extensions', 'webpack', 'werkzeug', 'wordpress', 'xslt & xpath', 'yarn', 'yii'] + }, + { + name: 'Picular', + url: 'https://picular.co', + keywords: ['color', 'palette', 'color palette', 'primary color generator', 'fast', 'google image search', 'generator', 'hex codes'] + }, + { + name: 'Canva Wireframe Templates', + url: 'https://www.canva.com/templates/?query=wireframe', + keywords: ['canva', 'wireframe', 'template', 'prototype', 'project', 'design'] + }, + { + name: 'Python Tutor: Visualize Code in Python, JavaScript, C, C++, and Java', + url: 'https://pythontutor.com/visualize.html#mode=edit', + keywords: ['code', 'visualize', 'python', 'javascript', 'c', 'c++', 'javascript', 'java', 'visualize execution', 'coding tutor', 'debug', 'supplement', 'recursion', 'execution', 'frames', 'objects', 'steps'] + }, + { + name: 'Unscreen', + url: 'https://www.unscreen.com', + keywords: ['remove video background', 'video', 'background', 'free', 'hd', 'no watermark', 'api plugins', 'plugins', 'clips', 'video file', 'audio', 'gif', 'presentation', 'remove', '.mp4', '.mov', '.gif', 'url', 'footage', 'record', 'video editing'] + }, + { + name: 'Quicktools by Picsart', + url: 'https://tools.picsart.com/image/background-remover/', + keywords: ['remove', 'background remover', 'image', 'picture', 'transparent', 'ai', 'free', 'refine', 'backgrounds', 'shadows', 'borders'] + }, + { + name: 'Squoosh', + url: 'https://squoosh.app', + keywords: ['compress image', 'reduce file size', 'reduce', 'high quality', 'image', 'smaller file', 'file size', 'privacy', 'image optimizer', 'compress', 'codecs', 'resize', 'convert image', 'convert', 'free', 'open-source', 'pixels', 'real-time', 'jpg', 'png', 'webp', 'avif'] + }, + { + name: 'Warp', + url: 'https://www.warp.dev', + keywords: ['terminal', 'gpu', 'crdt', 'rust', 'zsh', 'fish', 'bash', 'modern', 'development', 'code editor', 'writing code', 'code', 'commands', 'selections', 'cursor positioning', 'ai', 'shell commands', 'terminal sharing', 'customize', 'cli', 'command line'] + }, + { + name: 'Uiverse', + url: 'https://uiverse.io', + keywords: ['ui', 'ui elements', 'open-source', 'free', 'button', 'checkbox', 'toggle', 'switches', 'cards', 'loaders', 'inputs', 'css', 'html', 'hover', 'copy paste', 'cssbuttons'] + }, + { + name: 'Loaders', + url: 'https://cssloaders.github.io', + keywords: ['css', 'html', 'loader', 'loaders', 'animations', 'speed', 'simplicity', 'spinners', 'styling', 'pseudo elements', 'website', 'frontend'] + }, + { + name: 'Postman', + url: 'https://www.postman.com', + keywords: ['api', 'api platform', 'data', 'api lifecycle', 'collaboration', 'design', 'build', 'test', 'iterate', 'documentation', 'workspace', 'rest api', 'accessibility', 'http requests', 'tracking'] + }, + { + name: 'Screeps', + url: 'https://screeps.com', + keywords: ['sandbox', 'game', 'open-source', 'ai', 'programming', 'javascript', 'mmo', 'rts', 'player', 'scripting', 'steam', 'multiplayer', 'strategy game', 'colony', 'resources', 'mine', 'units', 'territory'] + }, + { + name: 'Oh My Posh', + url: 'https://ohmyposh.dev', + keywords: ['theme engine', 'shell', 'color', 'terminal', 'prompt', 'render', 'customizable', 'theme', 'powershell', 'windows', 'macos', 'linux', 'fonts', 'console', 'full color set', 'prompt string', 'function', 'variable'] + }, + { + name: 'Compressor', + url: 'https://compressor.io', + keywords: ['image compressor', 'image', 'fast', 'efficient', 'jpeg', 'png', 'svg', 'gif', 'webp', 'smaller images', 'faster website', 'optimized', 'seo', 'seo ranking', 'lighthouse', 'compression algorithm', 'shrink'] + }, + { + name: 'tiny png', + url: 'https://tinypng.com', + keywords: ['image compressor', 'image', 'fast', 'efficient', 'jpeg', 'png', 'webp', 'smaller images', 'transparent image', 'faster website', 'optimized', 'seo', 'seo ranking', 'lighthouse', 'compression algorithm', 'shrink'] + }, + { + name: 'Nerdy Data', + url: 'https://www.nerdydata.com', + keywords: ['search engine', 'source-code', 'tech stack', 'code', 'companies', 'leads', 'integrations', 'api access', 'domain', 'domain lookup', 'seo', 'google analytics', 'images', 'badges', 'websites', 'competitors'] + }, + { + name: 'Coolors', + url: 'https://coolors.co/palettes/trending', + keywords: ['color', 'color palettes', 'topics', 'styles', 'hex', 'hex values', 'color schemes', 'color combinations', 'design', 'free', 'css', 'generator'] + }, + { + name: 'Name Cheap Logo Maker', + url: 'https://www.namecheap.com/logo-maker/', + keywords: ['logo', 'logo maker', 'free', 'creator', 'business', 'branding'] + }, + { + name: 'Unsplash', + url: 'https://unsplash.com', + keywords: ['images', 'free', 'high-resolution', 'wallpapers', '3d renders', 'textures', 'patterns', 'experimental', 'architecture', 'nature', 'business and work', 'fashion', 'film', 'food', 'drink', 'street photography', 'arts and culture', 'royalty-free', 'stock photo', 'commercial', 'personal projects'] + }, + { + name: 'Page Speed', + url: 'https://pagespeed.web.dev', + keywords: ['page speed', 'web page', 'speed', 'load time', 'browser request', 'seo', 'optimization'] + }, + { + name: 'Cloud Convert', + url: 'https://cloudconvert.com/jpg-to-webp', + keywords: ['jpg', 'webp', 'converter', 'heic', 'formats', 'high-quality', 'api'] + }, + // Resource Format - please follow the styling below. + // { + // name: '', + // url: '', + // keywords: [''] + // }, ]; -exports.resources = resources; \ No newline at end of file +exports.resources = resources; diff --git a/server.js b/server.js index 765e7e5..f13c0b2 100644 --- a/server.js +++ b/server.js @@ -31,15 +31,14 @@ app.get('/api/:keyword', (req, res) => { // filter resources array, return items that match query; tag. const matches = resources.filter((obj) => obj.keywords.some(str => str.includes(keyword))); - try { - // if matches were found respond with json - if (matches.length) { - res.json(matches); - } else { - throw new Error('No resources found.'); - } - } catch(err) { - console.error(err); + // if matches were found, respond with matches array in JSON format + if (matches.length) { + res.json(matches); + } else { + // respond with status 404, no matches were found + res.status(404).json({ + error: `No resources were found with the ${keyword} keyword.` + }); } }); diff --git a/views/index.ejs b/views/index.ejs index 5948006..6f349c9 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -27,7 +27,7 @@