Skip to content
  • Unlock Pro
  • Log in with GitHub
Profile
OverviewSolutions
8
Comments
7

Joshua Dail

@joshdailAnn Arbor, MI290 points

Primarily frontend web development enthusiast with a special interest in making web sites accessible and easy to use

I’m currently learning...

Accessibility, React, Vite, Next.js

Latest solutions

  • IP Address Tracker with IPAPI and Leaflet

    #accessibility

    Joshua Dail•290
    Submitted about 2 years ago

    0 comments
  • Password Generator App with Added Accessibility (Typescript/Vite)

    #accessibility#vite#typescript

    Joshua Dail•290
    Submitted over 2 years ago

    0 comments
  • Dictionary Web App Built with React and Vite

    #react#vite

    Joshua Dail•290
    Submitted over 2 years ago

    0 comments
  • Planets fact site built with React and Vite

    #react#vite

    Joshua Dail•290
    Submitted over 2 years ago

    0 comments
  • Devjobs app built with Vite and React JS

    #vite#react

    Joshua Dail•290
    Submitted over 2 years ago

    0 comments
  • Responsive Easybank landing Page with added dark mode

    #accessibility

    Joshua Dail•290
    Submitted over 2 years ago

    0 comments
View more solutions

Latest comments

  • Imran Khan•370
    @astr0n0mer
    Submitted over 2 years ago

    Mobile-first solution using flexbox

    1
    Joshua Dail•290
    @joshdail
    Posted over 2 years ago

    Really nice job on this project. I also used absolute for getting the pop-up to work. It looks like your solution scales properly when the screen size changes, so I don't see any problem with it being absolutely positioned since it works and displays correctly.

    As far as whether to use h1 or img tag, I think that using an img tag, like you did, is better since an h1 tag is meant to be used for actual text. And you have the alt text for the image, so that takes care of the accessibility for the image. On a full website or app you would probably have an h1 somewhere else on the screen, but since this project is just a component I wouldn't worry about the h1 warning.

    Also really nice job making the buttons focusable and keyboard accessible!

    Marked as helpful
  • kxnzx•870
    @kxnzx
    Submitted over 2 years ago

    Tip Calculator App with Vanilla JavaScript

    #accessibility#sass/scss
    2
    Joshua Dail•290
    @joshdail
    Posted over 2 years ago

    I would suggest having the code for the error message in a separate function outside of your calculateAndDisplayValues function. That way calculateAndDisplayValues is focused just on the math, and you have another function focused just on the error message.

    So you could pull your error handling code outside of calculateAndDisplayValues and put it inside an event listener, something like this:

    document.getElementById("people").addEventListener("click",() => {
    let people = document.getElementById("people").value;
      // Convert the number of people to a number:
      /* If you want to treat the value as a number, 
      you can use the parseInt() or parseFloat() functions to convert it to a number. */
      people = parseInt(people, 10);
      // Check if the number of people is a valid number:
      if (isNaN(people) || people <= 0) {
        // Display an error message if the value is not valid:
        document.getElementById("error").innerHTML = "Can't be zero";
    document.getElementById("people").classList.add("invalid");
        return;
      } else  {
        document.getElementById("error").innerHTML = "";
    document.getElementById("people").classList.remove("invalid");
      } 
    })
    

    Then in calculateAndDisplayValues, you would still need to make sure that there is a valid input for number of people so you don't get NaN or divide by zero errors. You could have a line of code that checks to make sure there is a valid value before the function does the math, like this:

    if (people <= 0 || isNaN(people) {
    return;
    }
      let tipAmountPerPerson = (billAmount * tipPercentage) / 100 / people;
    

    Since the error message is taken care of by a separate function, you don't have to worry about it here in calculateAndDisplayValues. Here you're just concerned with making sure the math part of it works.

    I hope this is helpful.

    Marked as helpful
  • kxnzx•870
    @kxnzx
    Submitted over 2 years ago

    Tip Calculator App with Vanilla JavaScript

    #accessibility#sass/scss
    2
    Joshua Dail•290
    @joshdail
    Posted over 2 years ago

    Nice job!

    Looking at your solution, your form is not far off from working the way you want, just needs a few small tweaks to the code.

    For the error message: What you could do is have the HTML start off as an empty tag, with no text, like this:

    <small id="error" class="error"></small>
    

    and then have the event listener in your JS script add the error message to the element's innerText only if the error condition is met. Same with the red outline, you can have a CSS class, for example like this:

    .input.invalid {
      border: none;
      outline: 2px solid hsl(9, 31%, 58%);
    }
    

    And in your event listener, when you add in the error text, you can use <element>.classList.add (or remove) to add/remove the red background, like this:

    peopleInput.addEventListener("input", e => {
    
      const inputValue = peopleInput.value
      const peopleCount = Number(inputValue)
    
      if (peopleCount === 0 && peopleInput.value !== "") {
        peopleInput.classList.add(classInvalid)
      peopleErrorAlert.innerText = "Can't be zero"
        return
      }
    /* If no error make sure error message is not displayed */
      peopleInput.classList.remove(classInvalid)
      peopleErrorAlert.innerText = ""
    })
    

    For getting rid of "0", just set the value of the inputs to "" instead of "0" when the reset button is clicked. If you want it to show 0 as a placeholder, you could set the placeholder to 0 instead of the value, then the 0 will disappear as soon as a value is entered.

    Marked as helpful
  • SlavenaDuhneva•80
    @SlavenaDuhneva
    Submitted over 2 years ago

    Responsive NFT card using CSS with his unique capabilities for styling

    2
    Joshua Dail•290
    @joshdail
    Posted over 2 years ago

    Nice job!

    From what I can tell, your project is fine as far as appearing correctly on desktop and mobile. One good thing is that you are using rem for font sizes and not pixels. That can be important also for accessibility. Also, I see you are using CSS custom properties which are very helpful for responsive design.

    As far as responsive design for desktop/tablet/mobile, I generally will use media queries for different screen sizes. So I might have @media (width < some_width) for mobile, then another for tablet size, and so on. I will use Chrome or Firefox Devtools to see where the app starts to break or look incorrect at a certain width, and use that as a basis for where to switch from desktop to tablet or mobile.

    Using Flexbox and Grid for your page layouts is also great for responsiveness, since for Flexbox you can change rows to columns as the screen shrinks, and with Grid you can change the rows and columns as needed to fit different sizes.

    Kevin Powell has a great Youtube channel and also a free course on responsive design on his website https://www.kevinpowell.co, you may find that helpful

    Marked as helpful
  • Peculiar•90
    @s9trange
    Submitted over 2 years ago

    Fylo Data Storage Component

    1
    Joshua Dail•290
    @joshdail
    Posted over 2 years ago

    Here are a few things I've found helpful:

    Try to avoid setting definite widths when you can. I will usually set a width of 100% and then a max-width, like this:

    .section-menu {
      width: 100%;
      max-width: 22em;
    }
    

    That way, the element won't go wider than what you want, but it can also shrink with the page.

    Also, if you're using Flexbox for your main page sections, then when the width goes down, you can switch the flex-direction from row to column and make any other changes in the flex layout. So for example here, when the width drops, the sections shift from being in a row to stacking on top of one another, being centered, and being the same width:

    @media (width < 900px) and (orientation: portrait) {
      .container {
        flex-direction: column;
        align-items: center;
        padding-inline: 2em;
         }
        .section-menu,
        .section-meter {
          max-width: 22em;
        }
      }
    

    I had to write a lot of media queries for this project. What I found helpful was using the Chrome and Firefox dev tools, and trying out different screen sizes to see where the components started to break. Then I would write a media query to fix the problem. So I have one @media (width < 900px) with some rules, then another @media (width < 420px) with more rules, and so on. Just a lot of trial and error and experimenting until it looks the way you want it to.

  • Amer•360
    @amerrika
    Submitted over 2 years ago

    JavaScript Practice, not really mobile friendly xD

    1
    Joshua Dail•290
    @joshdail
    Posted over 2 years ago

    Nice job!

    It is possible to restrict the input fields. I also had a really hard time finding info online on how to do that. I used a combination of regular expressions and JS string methods and it seems to work.

    Here are the regex I used :

    const regexNumeralsDecimalsOnly = /[^0-9.]/g
    const regexNumeralsOnly = /[^0-9]/g
    

    I couldn't figure out how to control the number of decimal places with regex, so after filtering with the regex I used string methods to filter down to only one decimal point and two decimal places. Then it immediately rewrites the value in the input field with the filtered value.

    // First, filter the input value with regex, and escape out any invalid characters
    
    const filteredInput = billInput.value.replace(regexNumeralsDecimalsOnly, "")
    
      /* Force the input value to one decimal point and two decimal places at most
      The ternary expression looks for a decimal. If it finds one, it slices the string
     The first substring is the part before and including the decimal. The second part
     is after the decimal. Any additional decimals in the second substring are escaped
     out, and the length is limited to 2 characters */
    
      const inputValue =
        filteredInput.indexOf(".") >= 0
          ? filteredInput.substr(0, filteredInput.indexOf(".") + 1) +
            filteredInput.substr(filteredInput.indexOf(".") + 1, 2).replace(".", "")
          : filteredInput
    
    // Immediately the value in the input field with the filtered value,
    // preventing any invalid values from being entered
    
      billInput.value = inputValue
    

    Regexr.com is a good place to test out and learn about regex. Regex seems to be one of the best ways to filter input to what you want it to be.

View more comments
Frontend Mentor logo

Stay up to datewith new challenges, featured solutions, selected articles, and our latest news

Frontend Mentor

  • Unlock Pro
  • Contact us
  • FAQs
  • Become a partner

Explore

  • Learning paths
  • Challenges
  • Solutions
  • Articles

Community

  • Discord
  • Guidelines

For companies

  • Hire developers
  • Train developers
© Frontend Mentor 2019 - 2025
  • Terms
  • Cookie Policy
  • Privacy Policy
  • License

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub