Post image
Strategy

A dumb question about consistency for some tiles and URLs on…


TLDR; Probably best not to worry about this question ;p

So I’ve been working on a kids’ website for a while now, and part of my idea was to have just some fun facts & information for kids. I initially wanted to have categories where each category would be a different branch of science, however…

  • The branches of science are not exactly mutually exclusive (i.e. entomology is a branch of zoology)

  • Kids generally don’t search Google for “Zoology facts.” They are much more likely to search for “animal facts”

Up to this point I’ve had all of the tiles labeled with their branch of science in the larger font below and a descriptor above. But I’ve been considering changing it so that more recognizable fields remain as is, while the others are changed (i.e. “chemistry” and “physics” will stay the same, while “zoology” will become “animals” in the larger font–and “zoology” in the smaller font) so that they’re more identifiable for kids and more specific. This would also impact the URLs of the pages–i.e. site.com/zoology/elephants would become site.com/animals/elephants while site.com/physics/gravity would stay the same.

Anyway, I know I’m probably overthinking this, but I was wondering if this would be kind of a weird thing to do. #1, it kind of would imply to the kids that “zoology” is too complicated of a term for them, and #2 it just seems inconsistent. Also… as a #3, for some categories, like paleontology, I wouldn’t be sure whether to keep it as-is or to change it. I know this is super random and a dumb, rambly question, but if anyone has any advice or suggestions I’d greatly appreciate it 🙂

Post image



Source link

A Guide to Handling Browser Events Sarah Chima
Strategy

A Guide to Handling Browser Events Sarah Chima


'An event center'

Photo by Ambitious Creative Co. – Rick Barrett on Unsplash

Most web pages are interactive and users can perform actions on the web page. Examples of actions are clicking on a link, submitting a form or even scrolling through the web page.

There are times when you might want your page to behave in a certain way when the user performs a certain action. For instance, when a user clicks a button, you might want to display a modal. Or when a user fills a form on the page you might want to show the user if the input is valid. These actions are browser events.

In this article, we will discuss how we can handle events that occur in a browser. We will also discuss how to prevent default actions and what event propagation is. Let start right away.

An Introduction to Event Handlers

When an event occurs, we can tell the browser how to respond using event handlers. An event handler is a function that runs when an event occurs. There are three ways we add event handlers:

  1. Inline Event Handlers using HTML attribute
  2. DOM property
  3. Using the addEventListener method

Inline Event Handlers

A handler can be set using an HTML attribute. For instance, if we want a button to alert ‘hi’ whenever a user clicks the button we can do this:

<button onclick="alert('hi')">Say Hi</button>

We can also do this for a lot of other events using the same syntax.

Writing a lot of code in an HTML element might not be convenient. We can also write a function in a script and call the function in the on<event> attribute.

<button onclick="sayHi()">Say Hi</button>

<script>
    function sayHi() {
        console.log('Hi')
    }
</script>

DOM Property

Another way to handle an event is by using the DOM property. Let us use the example above to do this.

<button>Say Hi</button>

<script>
    var button = document.querySelector('button');
    button.onclick = () => {
        console.log('hi')
    }
</script>

This produces the same result as the previous method.

What happens when we apply an inline event handler and a JavaScript handler to the same element?

<button onclick="console.log('hi')">Say Hi</button>

<script>
    var button = document.querySelector('button');
    button.onclick = () => {
        console.log('no')
    }
</script>

The JavaScript handler takes precedence over the inline handler so ‘no’ is logged.

The addEventListener method

We can use the addEventListener method to listen for an event on a particular DOM element. Using this method, we provide a method that handles such an event. One advantage of this method is that it allows you to register as many events as possible on an element.

This is the syntax of the addEventListener method.

target.addEventListener(type, function, useCapture)

Target is the element you want to listen for an event on.

Type is the type of event you want to listen for. For example, if it is a button, you can listen for a click event.

The function is the event handler. It specifies the function is carried out when an event occurs.

useCapture is optional. It is a boolean that specifies whether an event should be used in the capturing or bubbling phase. If it is true, it is used in the capturing phase. If it is false (default value), it is used in the bubbling phase. We will touch more on this later.

Here is an example of using this method.

<button>Say Hi</button>

<script>
    let button = document.querySelector('button');
    button.addEventListener('click', () => {
        console.log('Hi') 
    })
</script>

In this case, button is my target, the type of event is click, the arrow function is the function that is executed when this code runs. If you run this code, anytime the button is clicked, you get ‘Hi’ in the console.

A named function can also be passed as the callback function.

The Event Object

When an event occurs, the browser creates an event object and passes it as an argument to the event handler. This event object contains details of the event. For instance, you might want to know which button was clicked or which key was pressed or the mouse coordinates when the event occurred. You can get all of these from the event object.

Using our example above, we can do this:

<button>Say Hi</button>

<script>
    let button = document.querySelector('button');
    button.addEventListener('click', (event) => {
        console.log(event.clientX) 
        console.log(event.clientY) 
    })
</script>

It prints the x any y-coordinates of where the event occurred which in this case is 41 and 19 respectively.

The information stored in the event depends on the type of event that occurred. To get full details of the event object, you can log the event object to the console console.log(event). In any case, it always has a type property that tells the type of event that occurred.

Default Actions

When an event occurs on some elements, there are actions that take place by default. For instance, when a link is clicked, it takes you to the link’s target. When a button inside a form is clicked, the form is submitted. These are default actions of the browser.

Event handlers are called for most events before the default takes place. It is possible to prevent the default action using the event.preventDefault() method. This method stops the default action from taking place. Here is an example:

<a href="https://sarahchima.com">Sarah Chima</a>

<script>
    let link = document.querySelector('a');
    link.addEventListener('click', (event) => {
        console.log("Nope, you ain't visiting her today")
        event.preventDefault()
    })
</script>

When this link is clicked, it does not take you to the expected URL, rather it logs the statement into the console.

This can also be used to implement keyboard shortcuts on a page or a context menu.

However, for good user experience, it is best to avoid intercepting expected behaviour of an element. Such actions might make the user think that your website is broken.

Events and Propagation

When an event occurs on an element, the event handler on the target element first runs. Then the handler of its immediate parent, if any, runs and that of its parent’s parent all the way up to outermost element that has a handler. This is called propagation.

An example will do some good here.

<style>
    * {
        border: 1px solid green;
        margin: 15px
    }
</style>
<div onclick="alert('div')"> DIV
    <p onclick="alert('p')"> P 
        <span onclick="alert('span')"> SPAN</span>
    </p>
</div>

I added a little style to differentiate the elements. If you run this HTML code and click on the span element, you will notice that three handlers are fired. First, the one on the span, next, the one on the p tag and then the one on the div tag. This because when an event occurs it propagates to the outer elements and their handlers are also triggered.

There are two types of propagation that can occur in an element: Bubbling and Capturing. We have seen this before when we were discussing the syntax of the addEventListener method.

The difference between bubbling and capturing is that in the bubbling phase, events propagate outwards. That is, the handler on the innermost element gets triggered first, then the parent all the way up.

In capturing, the reverse occurs. The handler on the outermost element is triggered first and then the child handler all the way down to the element where the event occurred. This is the reverse of what occurred in our example.

For event handlers, bubbling is the default but if the capture argument is set to true, then capturing occurs. To learn more about this, you can read this article on it.

You might not want this propagation behaviour to occur when you click on an element. Thankfully, JavaScript provides a way to do so. To stop propagation, you can call the event.stopPropagation() method. This method prevents events from propagating.

In our previous example, we can do this:

<div onclick="alert('div')"> DIV
    <p onclick="alert('p')"> P 
        <span> SPAN</span>
    </p>
</div>

<script>
    var span = document.querySelector('span');
    span.addEventListener('click', (event) => {
        alert('span')
        event.stopPropagation();
    }
</script>

If you run this code, you will notice that only the handler on the span is triggered.

As with all default behaviours, preventing propagation should only be done when it is necessary.

One last thing before we go.

Removing an Event Listener

It is possible to remove an event listener using the removeEventListener method. We use it the same way we use the addEventListener method. We pass in the type and the function just the same way. However, the function must be stored in a variable for it to work.

Here is an example

<button>Say Hi</button>

<script>
    let button = document.querySelector('button');

    function sayHi() {
        console.log('Hi')
    }
    button.addEventListener('click', sayHi)
    button.removeEventListener('click', sayHi)
</script>

Run this code and notice that the event listener function never runs. This is because the eventListener has been removed.

If we do not store the function in a variable like in the example below, the removeEventListener will not work.

<button>Say Hi</button>

<script>
    let button = document.querySelector('button');
    button.addEventListener('click', () => {
        console.log('hi')
    })
    button.removeEventListener('click',  () => {
        console.log('hi')
    })
</script>

Conclusion

We discussed how we can handle events using HTML attributes, DOM property and the addEventListener method. We saw that we can prevent default actions by using the event.preventDefault method. We also learnt about event propagation.

Handling events can help you control the way the browser responds to user actions and we have discussed how we can do this. In my next article, I will discuss 10 common events that can occur in a browser.



Source link

Get Started Building GraphQL APIs With Node
Strategy

Get Started Building GraphQL APIs With Node


We all have a number of interests and passions. For example, I’m interested in JavaScript, 90’s indie rock and hip hop, obscure jazz, the city of Pittsburgh, pizza, coffee, and movies starring John Lurie. We also have family members, friends, acquaintances, classmates, and colleagues who also have their own social relationships, interests, and passions. Some of these relationships and interests overlap, like my friend Riley who shares my interest in 90’s hip hop and pizza. Others do not, like my colleague Harrison, who prefers Python to JavaScript, only drinks tea, and prefers current pop music. All together, we each have a connected graph of the people in our lives, and the ways that our relationships and interests overlap.

These types of interconnected data are exactly the challenge that GraphQL initially set out to solve in API development. By writing a GraphQL API we are able to efficiently connect data, which reduces the complexity and number of requests, while allowing us to serve the client precisely the data that it needs. (If you’re into more GraphQL metaphors, check out Meeting GraphQL at a Cocktail Mixer.)

In this article, we’ll build a GraphQL API in Node.js, using the Apollo Server package. To do so, we’ll explore fundamental GraphQL topics, write a GraphQL schema, develop code to resolve our schema functions, and access our API using the GraphQL Playground user interface.

What is GraphQL?

GraphQL is an open source query and data manipulation language for APIs. It was developed with the goal of providing single endpoints for data, allowing applications to request exactly the data that is needed. This has the benefit of not only simplifying our UI code, but also improving performance by limiting the amount of data that needs to be sent over the wire.

What we’re building

To follow along with this tutorial, you’ll need Node v8.x or later and some familiarity with working with the command line. 

We’re going to build an API application for book highlights, allowing us to store memorable passages from the things that we read. Users of the API will be able to perform “CRUD” (create, read, update, delete) operations against their highlights:

  • Create a new highlight
  • Read an individual highlight as well as a list of highlights
  • Update a highlight’s content
  • Delete a highlight

Getting started

To get started, first create a new directory for our project, initialize a new node project, and install the dependencies that we’ll need:

# make the new directory
mkdir highlights-api
# change into the directory
cd highlights-api
# initiate a new node project
npm init -y
# install the project dependencies
npm install apollo-server graphql
# install the development dependencies
npm install nodemon --save-dev

Before moving on, let’s break down our dependencies:

  • apollo-server is a library that enables us to work with GraphQL within our Node application. We’ll be using it as a standalone library, but the team at Apollo has also created middleware for working with existing Node web applications in ExpresshapiFastify, and Koa.
  • graphql includes the GraphQL language and is a required peer dependency of apollo-server.
  • nodemon is a helpful library that will watch our project for changes and automatically restart our server.

With our packages installed, let’s next create our application’s root file, named index.js. For now, we’ll console.log() a message in this file:

console.log("📚 Hello Highlights");

To make our development process simpler, we’ll update the scripts object within our package.json file to make use of the nodemon package:

"scripts": {
  "start": "nodemon index.js"
},

Now, we can start our application by typing npm start in the terminal application. If everything is working properly, you will see 📚 Hello Highlights logged to your terminal.

GraphQL schema types

A schema is a written representation of our data and interactions. By requiring a schema, GraphQL enforces a strict plan for our API. This is because the API can only return data and perform interactions that are defined within the schema. The fundamental component of GraphQL schemas are object types. GraphQL contains five built-in types:

  • String: A string with UTF-8 character encoding
  • Boolean: A true or false value
  • Int: A 32-bit integer
  • Float: A floating-point value
  • ID: A unique identifier

We can construct a schema for an API with these basic components. In a file named schema.js, we can import the gql library and prepare the file for our schema syntax:

const { gql } = require('apollo-server');

const typeDefs = gql`
  # The schema will go here
`;

module.exports = typeDefs;

To write our schema, we first define the type. Let’s consider how we might define a schema for our highlights application. To begin, we would create a new type with a name of Highlight:

const typeDefs = gql`
  type Highlight {
  }
`;

Each highlight will have a unique ID,  some content, a title, and an author. The Highlight schema will look something like this:

const typeDefs = gql`
  type Highlight {
    id: ID
    content: String
    title: String
    author: String
  }
`;

We can make some of these fields required by adding an exclamation point:

const typeDefs = gql`
  type Highlight {
    id: ID!
    content: String!
    title: String
    author: String
  }
`;

Though we’ve defined an object type for our highlights, we also need to provide a description of how a client will fetch that data. This is called a query. We’ll dive more into queries shortly, but for now let’s describe in our schema the ways in which someone will retrieve highlights. When requesting all of our highlights, the data will be returned as an array (represented as [Highlight]) and when we want to retrieve a single highlight we will need to pass an ID as a parameter.

const typeDefs = gql`
  type Highlight {
    id: ID!
    content: String!
    title: String
    author: String
  }
  type Query {
    highlights: [Highlight]!
    highlight(id: ID!): Highlight
  }
`;

Now, in the index.js file, we can import our type definitions and set up Apollo Server:

const {ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');

const server = new ApolloServer({ typeDefs });

server.listen().then(({ url }) => {
  console.log(`📚 Highlights server ready at ${url}`);
});

If we’ve kept the node process running, the application will have automatically updated and relaunched, but if not, typing npm start  from the project’s directory in the terminal window will start the server. If we look at the terminal, we should see that nodemon is watching our files and the server is running on a local port:

[nodemon] 2.0.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
📚 Highlights server ready at http://localhost:4000/

Visiting the URL in the browser will launch the GraphQL Playground application, which provides a user interface for interacting with our API.

GraphQL Resolvers

Though we’ve developed our project with an initial schema and Apollo Server setup, we can’t yet interact with our API. To do so, we’ll introduce resolvers. Resolvers perform exactly the action their name implies; they resolve the data that the API user has requested. We will write these resolvers by first defining them in our schema and then implementing the logic within our JavaScript code. Our API will contain two types of resolvers: queries and mutations.

Let’s first add some data to interact with. In an application, this would typically be data that we’re retrieving and writing to from a database, but for our example let’s use an array of objects. In the index.js file add the following:

let highlights = [
  {
    id: '1',
    content: 'One day I will find the right words, and they will be simple.',
    title: 'Dharma Bums',
    author: 'Jack Kerouac'
  },
  {
    id: '2',
    content: 'In the limits of a situation there is humor, there is grace, and everything else.',
    title: 'Arbitrary Stupid Goal',
    author: 'Tamara Shopsin'
  }
]

Queries

A query requests specific data from an API, in its desired format. The query will then return an object, containing the data that the API user has requested. A query never modifies the data; it only accesses it. We’ve already written a two queries in our schema. The first returns an array of highlights and the second returns a specific highlight. The next step is to write the resolvers that will return the data.

In the index.js file, we can add a resolvers object, which can contain our queries:

const resolvers = {
  Query: {
    highlights: () => highlights,
    highlight: (parent, args) => {
      return highlights.find(highlight => highlight.id === args.id);
    }
  }
};

The highlights query returns the full array of highlights data. The highlight query accepts two parameters: parent and args. The parent is the first parameter of any GraqhQL query in Apollo Server and provides a way of accessing the context of the query. The args parameter allows us to access the user provided arguments. In this case, users of the API will be supplying an id argument to access a specific highlight.

We can then update our Apollo Server configuration to include the resolvers:

const server = new ApolloServer({ typeDefs, resolvers });

With our query resolvers written and Apollo Server updated, we can now query API using the GraphQL Playground. To access the GraphQL Playground, visit http://localhost:4000 in your web browser.

A query is formatted as so:

query {
  queryName {
      field
      field
    }
}

With this in mind, we can write a query that requests the ID, content, title, and author for each our highlights:

query {
  highlights {
    id
    content
    title
    author
  }
}

Let’s say that we had a page in our UI that lists only the titles and authors of our highlighted texts. We wouldn’t need to retrieve the content for each of those highlights. Instead, we could write a query that only requests the data that we need:

query {
  highlights {
    title
    author
  }
}

We’ve also written a resolver to query for an individual note by including an ID parameter with our query. We can do so as follows:

query {
  highlight(id: "1") {
    content
  }
}

Mutations

We use a mutation when we want to modify the data in our API. In our highlight example, we will want to write a mutation to create a new highlight, one to update an existing highlight, and a third to delete a highlight. Similar to a query, a mutation is also expected to return a result in the form of an object, typically the end result of the performed action.

The first step to updating anything in GraphQL is to write the schema. We can include mutations in our schema, by adding a mutation type to our schema.js file:

type Mutation {
  newHighlight (content: String! title: String author: String): Highlight!
  updateHighlight(id: ID! content: String!): Highlight!
  deleteHighlight(id: ID!): Highlight!
}

Our newHighlight mutation will take the required value of content along with optional title and author values and return a Highlight. The updateHighlight mutation will require that a highlight id and content be passed as argument values and will return the updated Highlight. Finally, the deleteHighlight mutation will accept an ID argument, and will return the deleted Highlight.

With the schema updated to include mutations, we can now update the resolvers in our index.js file to perform these actions. Each mutation will update our highlights array of data.

const resolvers = {
  Query: {
    highlights: () => highlights,
    highlight: (parent, args) => {
      return highlights.find(highlight => highlight.id === args.id);
    }
  },
  Mutation: {
    newHighlight: (parent, args) => {
      const highlight = {
        id: String(highlights.length + 1),
        title: args.title || '',
        author: args.author || '',
        content: args.content
      };
      highlights.push(highlight);
      return highlight;
    },
    updateHighlight: (parent, args) => {
      const index = highlights.findIndex(highlight => highlight.id === args.id);
      const highlight = {
        id: args.id,
        content: args.content,
        author: highlights[index].author,
        title: highlights[index].title
      };
      highlights[index] = highlight;
      return highlight;
    },
    deleteHighlight: (parent, args) => {
      const deletedHighlight = highlights.find(
        highlight => highlight.id === args.id
      );
      highlights = highlights.filter(highlight => highlight.id !== args.id);
      return deletedHighlight;
    }
  }
};

With these mutations written, we can use the GraphQL Playground to practice mutating the data. The structure of a mutation is nearly identical to that of a query, specifying the name of the mutation, passing the argument values, and requesting specific data in return. Let’s start by adding a new highlight:

mutation {
  newHighlight(author: "Adam Scott" title: "JS Everywhere" content: "GraphQL is awesome") {
    id
    author
    title
    content
  }
}

We can then write mutations to update a highlight:

mutation {
  updateHighlight(id: "3" content: "GraphQL is rad") {
    id
    content
  }
}

And to delete a highlight:

mutation {
  deleteHighlight(id: "3") {
    id
  }
}

Wrapping up

Congratulations! You’ve now successfully built a GraphQL API, using Apollo Server, and can run GraphQL queries and mutations against an in-memory data object. We’ve established a solid foundation for exploring the world of GraphQL API development.

Here are some potential next steps to level up:



Source link

Post image
Strategy

Failing to animate a custom hamburger icon : web_design


Post image

Custom Hamburger Icon

html

<div class="menu-icon">
    <span class="menu-icon__line menu-icon__line-left"></span>
    <span class="menu-icon__line"></span>
    <span class="menu-icon__line menu-icon__line-right"></span>
</div>

css

.menu-icon {
    height: 30px;
    width: 30px;
    z-index: 1;
    cursor: pointer;
}

.menu-icon {
    height: 14px;
    width: 30px;
    position: fixed;
    cursor: pointer;
}

.menu-icon__line {
    height: 2px;
    width: 30px;
    display: block;
    background-color: #fff;
    margin-bottom: 4px;
}

.menu-icon__line-left {
    width: 15px;
    transition: width 0.2s;
}

.menu-icon__line-right {
    width: 10px;
    float: right;
    transition: width 0.2s;
}

.menu-icon__line-left:hover, .menu-icon__line-right:hover {
    width: 30px;
}

I tried using JS to trigger mouseover on menu-icon lines when a user hovers on the menu icon but it doesn’t work. This code only animates when you specifically hover over the given lines and not when you’re on the menu icon which is understandable.

I tried using dispatchEvent in JS too. It isn’t working. Is there any way that I can trigger the animation on menu-icon lines when someone hovers on menu-icon?



Source link

Aspen Ridge Logo
Strategy

Aspen Ridge Logo


Aspen Ridge Logo

Hey guys this is an attempt at a fictional company based in Aspen Colorado. It is a luxury resort in the middle of the Rocky Mountains. The mark is based off an aspen tree leaf. Please give me feedback. Thank you!

https://preview.redd.it/l50ue351ecm41.jpg?width=2400&format=pjpg&auto=webp&s=631cb4fe0dd2da515dda329fb50ef3e5eb4b6fc9

submitted by /u/siimbaz
[comments]



Source link