Implementing Themes in Angular JS for Susper

Adding themes to any website, makes it more interesting to use, and also helps customize the website according to personal preferences. This blog deals with how we implemented themes in Susper.
Susper offers the following themes

  • Default
  • Dark
  • Basic
  • Contrast
  • Terminal

This is how some of the themes look
Dark:

Contrast:  
Terminal:
Lets go through a step by step guide how to implement this:

  1. Add a Themes service  (In app/src/theme.service.ts in Susper)

Here is the code snippet:

import { Injectable } from ‘@angular/core’;

@Injectable()
export class ThemeService {

public titleColor: string;
public linkColor: string;
public descriptionColor: string;
public backgroundColor: string;

constructor() { }

}

  1.  Create a component for themes, and define functions for various themes in the .ts file.(src/app/theme/theme.component.ts in Susper)

Here is the example code:

import { Component, OnInit } from ‘@angular/core’;
import { ThemeService } from ‘../theme.service’;@Component({
selector: ‘app-theme’,
templateUrl: ‘./theme.component.html’,
styleUrls: [‘./theme.component.css’]
})
export class ThemeComponent implements OnInit {constructor(
private themeService: ThemeService
) { }ngOnInit() {
}darkTheme() {
this.themeService.backgroundColor = ‘#FFFFFF’;
this.themeService.titleColor = ‘#050404’;
this.themeService.linkColor = ‘#7E716E’;
this.themeService.descriptionColor = ‘#494443’;
}

defaultTheme() {
this.themeService.backgroundColor = ‘#FFFFFF’;
this.themeService.titleColor = ‘#1a0dab’;
this.themeService.linkColor = ‘#006621’;
this.themeService.descriptionColor = ‘#545454’;
}

basicTheme() {
this.themeService.backgroundColor = ‘#FFFFFF’;
this.themeService.titleColor = ‘#1a0dab’;
this.themeService.linkColor = ‘#494443’;
this.themeService.descriptionColor = ‘#7E716E’;
}

In the above code, the first few lines  include the constructor, which defines the theme service, and include a default function that runs as soon as the page is initialized.

We then see three kinds of themes implemented, dark, default and contrast. Let us examine the darkTheme:

darkTheme() {
this.themeService.backgroundColor = ‘#FFFFFF’;
this.themeService.titleColor = ‘#050404’;
this.themeService.linkColor = ‘#7E716E’;
this.themeService.descriptionColor = ‘#494443’;
}
  • The first line sets the background color of the screen(to white).
  • The second line is used to set the color of all the titles of the search results
  • The third line is used to set the link/url color
  • The fourth line sets the description color
    1.   Link the appropriate attributes in your html pages, using [style.’css-attribute’]

(src/app/results/results.component.html in Susper)

Following this example, you can link different parts of the html file to the attributes in your theme service and you are done!
If implementing this in a project like Susper, a few points of caution:

  • Make sure you write your spec.ts file well, and add your component for proper compilation and testing.
  • Do not forget to import the service into any component before you use it in its html files.

Resources 

Continue ReadingImplementing Themes in Angular JS for Susper

Implementing a Pagination Bar in Susper Angular JS Frontend

Searching on Susper most queries will have a number of search results. These results may span over several pages, and hence, a well designed pagination bar becomes essential for easy navigation. This blog deals with how we created the pagination bar in Susper. This is how the pagination bar in Susper looks:

There are a maximum of 10 pages displayed at any point of time.
At times you may have lesser results too:

where you can either directly click on a page or use the Previous and Next buttons for navigation. As you move along the pages, this is how it looks:

We will now see how we go about creating this bar.
The html source code( with a line by line explanation of the code):

<div class=“pagination-bar”>
<div class=“pagination-property” *ngIf=“noOfPages>1”>
<nav arialabel=“Page navigation” *ngIf=“(items$ | async)?.length!=0”>
  • Previous button is used to decrease the current page number, clicking on the first S in ‘Susper’ also accomplishes this task. Notice that this button is to be displayed only if you are not already on the first page of Susper.
<li class=“page-item” *ngFor=“let num of getNumber(maxPage)”><span class=“page-link” *ngIf=“presentPage>=4 && presentPage-3+num<=noOfPages” [class.active_page]=”getStyle(presentPage-3+num)”
(click)=”getPresentPage(presentPage-3+num)” href=“#”>

[class.active_page]=”getStyle(presentPage-3+num)” class=“page-text”>U

class=“page-number”>{{presentPage-3+num}}</span></span>
<span class=“page-link” *ngIf=“presentPage<4 && num<=noOfPages” [class.active_page]=”num+1 == presentPage (click)=”getPresentPage(num+1)”
href=“#”>

[class.active_page]=”num+1 == presentPage class=“page-text”>U</span>

class=“page-number”>{{num+1}}</span></span></li>

  • The above lines specify that we want to update our pagination bar only if the user has navigated more than the first three pages  
  • class.active_page gives correct css for the active page and getStyle() tells whether that particular page is active or not  
  • getPresentPage() uses the current page number to calculate which results to display  

<li class=“page-item”><span class=“page-link” (click)=”incPresentPage()”>

class=“page-text next”>SPER

</span></li>
<li class=“page-item2” *ngIf=“!getStyle(maxPage)”><span class=“spl” (click)=”incPresentPage()”>

class=“arrow”>>
class=“side-text”>Next

</span></li></ul>
</div>
</nav>
</div>

  • This part is used to increment the present page, and show the next/SPER message. Notice that it should be displayed only if you are not already on the last page

The attached typescript functions:

incPresentPage() {
this.presentPage = Math.min(this.noOfPages, this.presentPage + 1);
this.getPresentPage(this.presentPage);
}decPresentPage() {
this.presentPage = Math.max(1, this.presentPage 1);
this.getPresentPage(this.presentPage);
}
  • incPresentPage() increments the present page, if possible(that is you have not reached your maximum pages already).
  • decPresentPage() decrements the present page, if possible(that is you have not reached page 1 already).

getStyle(page) {
return ((this.presentPage) === page);
}
  • getStyle() returns true if passed page is the present page, useful to apply different css classes to the active page

getPresentPage(N) {
this.presentPage = N;
let urldata = Object.assign({}, this.searchdata);
urldata.start = (this.presentPage 1) * urldata.rows;
this.store.dispatch(new queryactions.QueryServerAction(urldata));}
  • getPresentPage () is used to change the page, and navigate to the page, with the correct rows of data

And you are done! You now have a working pagination bar to plugin at the bottom of your search results!

You can check out this elaborate tutorial on implementing Pagination bars from w3 schools : https://www.w3schools.com/css/css3_pagination.asp

Continue ReadingImplementing a Pagination Bar in Susper Angular JS Frontend

Making the footer-navigation bar stick to the bottom in Susper

In Susper, we have a navigation bar as a footer, as shown:

Previously this footer-navbar would appear immediately after the content, even if it was in the middle of the page. This is how the footer would appear:Since this could be a very common problem on a lot of websites, this blog deals with a simple hack for it.  

  1. Design your footer navbar as you please. You need not use any predefined bootstrap classes. You also need not specify any parameters regarding the position of the navbar (relative, absolute etc.).
  2. Enclose the rest of the data on your webpage in a div tag, do not forget to mention a class name or id name for the tag.  
  3. Now comes the simplest trick: Set a minimum height for your div! It is advisable to use vh (viewport-height) as your unit of measurement since it is easy to estimate how much of the viewport needs to be covered by your width.

This is how it is used in Susper:

Remember that each vh corresponds to one-hundredth of the viewport total height. So 100 vh here will mean a minimum height of the full viewport.

You can check the Susper repository for the source code or go through this link for alternate ways to create a sticky footer at the bottom.

Continue ReadingMaking the footer-navigation bar stick to the bottom in Susper

Refactor of Dropdown Menu in Susper

The first version of the Susper top menu was providing links to resources and tutorials. In the next version of the menu, we were looking for a menu with more colorful icons, a cleaner UI design and a menu that should appear on the homepage as well. In this blog, I will discuss about refactoring the dropdown menu. This is how earlier dropdown of Susper looks like:

We decided to create a separate component for the menu DropdownComponent.

At first, I created a drop down menu with matching dimensions similar to what Google follows. Then, I gave padding: 28px to create similar UI to market leader. This will make a dropdown menu with clean UI design. I replaced the old icons with colorful icons. In the dropdown we have:

  • Added more projects of FOSSASIA like eventyay, loklak, susi and main website of FOSSASIA. Here how it looks now :

The main problem I faced was aligning the content inside the dropdown and they should not get disturbed when the screen size changes.
I kept the each icon dimensions as 48 x 48 inside drop down menu. I also arranged them in a row. It was easy to use div element to create rows rather than using ul and li tags which were implemented earlier.

To create a horizontal grey line effect, I used the hr element. I made sure, padding remained the same above and below the horizontal line.

At the end of drop down menu, @mariobehling suggested instead of writing ‘more’, it should redirect to projects page of FOSSASIA.

This is how I worked on refactoring drop down menu and added it on the homepage as well.

Resources

Continue ReadingRefactor of Dropdown Menu in Susper

Responsive Image Overlay

Image overlay is a very common concept in front-end development. It is easy to implement but difficult when we deal it with different screen sizes, where we need to cover the image with the overlay each time the screen size is changed. I have gone through various blog posts when I need to implement the same for Open-event webapp and researched a solution that works for all screen sizes without any media query.

1234

How to add an overlay to an image ?

If we need four images in a single row nearly 300*300px.  The code below shows the markup.

image-holder : The parent class to take the image and overlay inside it.

background-image: This class takes image source.

responsive-overlay: This is the key point to make it responsive. Responsive-overlay contains a class hover-state to add overlay absolutely and a class social-links.

social-links: It adds content to hover-state.

 

<div class="image-holder">
  <img class="background-image" alt="" src="">
   <div class="responsive-overlay">
     <div class="hover-state text-center preserve3d">
       <div class="social-links vertical-align">

       </div>
     </div>
   </div>
 </div>

The styling is written with SASS in .scss file as shown below.

//overlayimage and backgroundshade can be set in config.scss

 .image-holder {
   position: relative;
   overflow: hidden;
   margin-bottom: 12px;

   .background-image {
     height: 300px;
     width: 300px;
     display: block;
     margin: 0 auto;
     background-color: $background-shade;
    }
 
   .responsive-overlay {
     @include responsiveoverlay;

    .preserve3d {
       height: 300px;
      }

    .hover-state {
     @include hoverstate;
     height: 300px;
     width: 300px;
    }

  @mixin responsiveoverlay {
     height: 100%;
     position: absolute;
     top: 0;
     width: 100%;
}

   @mixin hoverstate {
     background: $overlayimage;
     display: block;
     height: 300px;
     left: 0;
     margin: 0 auto;
     opacity: 0;
     position: relative;
     top: 0;
     -moz-transition: all 0.3s ease-out;
     -webkit-transition: all 0.3s ease-out;
     transition: all 0.3s ease-out;
     width: 300px;
     z-index: 2;
   }

This code will work for responsiveness as well. The main catch here is the responsive-overlay class which is made 100% in width but set to position absolute. The images which are 300 * 300 px in size will take an overlay of the same size because of hover-state class. Instead, if we adjust sizes of images in small screens the above code will adjust overlay on the image automatically.

Like, on tablets we can have an overlay like this.

345

And on mobile screen output is like that :

23

Conclusion

Responsiveness is easy if we follow correct concepts. Here, the concepts of absolute and relative positioning in CSS have done the magic. Now we can play by adding different contents and effect on hover following the same basics.

Continue ReadingResponsive Image Overlay

Optimization with SASS

The problem with using CSS is that it can become repetitive when used in large projects. Like using same values of margins, paddings, radius. SASS provides a way to store these values in ONE variable and to use that variable instead.

SASS provides various concepts that optimize CSS. Like discussed above using variables for all the color names and fonts will remove the repetition. A piece of code from Open-Event-Webapp is shown below for declaring variable names.

//config.scss

@charset "UTF-8";
 
// Colors
$black: #000;
$white: #fff;
$red: #e2061c;
$gray-light: #c9c8c8;
$gray: #838282;
$gray-dark: #777;
$gray-extra-dark: #757575;
$gray-extra-light:#e7e7e7 !default;
$gray-perfect :#ddd;
$blue: #253652;
$orange: #e12b00;
$vivid-blue: #2196F3;
$pure-orange: #ff8700;
$light-purple: #ebccd1;
$red-dark: #e52d27;
$light-black: #333333;
$light-skyblue : #b7cdff !default;
$gray-trackshade: #999;
$blue-shade: #2482d3;
$dark-black: rgba(22, 22, 22, 0.99) !default;
$black-main:#232323 !default;
$timeroom-color:rgba(0,0,0,.10) !default;
$session-color: $gray-trackshade !default;
$header-color: #f8f8f8 !default;
$main-background: #fff !default;

// Corp-Colors
$corp-color: $white !default;
$corp-color-dark: darken($corp-color, 15%) !default;
$corp-color-second: $red !default;
$corp-color-second-dark: darken($corp-color-second, 15%) !default;

Nesting

SASS supports nesting concept. The nested SCSS changes to CSS when compiled. A good approach follows nesting elements to three-degree maximum.

// Nesting in application.scss session-list (Open-Event-Webapp)

.session{

  &-list {

    li{
     cursor: pointer;
      }
   .label {
     background: #ff8700;
     border-color: $light-purple;
     color: #FFFFFF;
     font-weight: 500;
     font-size: 80%;
     margin-left: -8px;
    }
   .session-title {
      margin-top: 0.1em;
       .session-link {
         font-size: 12px;
        }
    }
 }
 &-location{
 text-align: left;
 }

}

The output generated after compilation will be

//Code from schedule.css in Open-event-webapp

.session-list li {
 cursor: pointer; 
}

.session-list .label {
 background: #ff8700;
 border-color: #ebccd1;
 color: #FFFFFF;
 font-weight: 500;
 font-size: 80%;
 margin-left: -8px; 
}

.session-list .session-title {
 margin-top: 0.1em; 
}

 .session-list .session-title .session-link {
 font-size: 12px;
 }

.session-location {
 text-align: left; 
}

Mixins

Mixins are another way to optimize the SASS code. Mixins are just like functions that let us pass the values as parameters to make the code more flexible.

// Simple mixin for button
@mixin btn($color, $width, $height) {
 display: block;
 font: 16px “Open sans”, arial;
 color: $color;
 width: $width;
 height: $height;
}

Using these type of simple approaches make CSS more effective and efficient. It will enhance the workflow and help us to write cleaner code.

Continue ReadingOptimization with SASS

Responsive UI: Modifying Designs with Device Width

An important feature of websites these days with the advancement of smartphones is being responsive with device size. We nowadays not only worry about the various width of laptop or desktop, which don’t vary by a huge amount but also need to worry about tablets and phones which have a much lesser width. The website’s UI should not break and should be as easy to use on phones as it is on desktops/laptops. Using frameworks like bootstraps, Semantic-UI solves this problem to a large extent. But what if we need to modify certain parts by our own in case of mobile devices? How do we do that?

Continue ReadingResponsive UI: Modifying Designs with Device Width

Building interactive elements with HTML and javascript: Resizing

{ Repost from my personal blog @ https://blog.codezero.xyz/building-interactive-elements-with-html-and-javascript-resizing }

Unlike draggable, HTML/js does not provide us with a direct spec for allowing users to graphically resize HTML DOM elements. So, we’ll be using mouse events and pointer locations to achieve the ability of resizing.

We’ll start with a box div.

<div id="box">  
    <div>Resize me !</div>
</div>  

A little bit of CSS magic to make it look a little bit better and square.

#box {
    position: relative;
    width: 130px;
    height: 130px;
    background-color: #2196F3;
    color: white;
    display:flex;
    justify-content:center;
    align-items:center;
    border-radius: 10px;
}

Now, we need a handle element. The user will be using this handle element to drag and resize the box.

<div id="box">  
    <div>Resize me !</div>
    <div id="handle">
    </div>
</div>  

Now, we just have an invisible div. Let’s give it some color, make it square. We also have to position it at one corner of the box.

#handle {
    background-color: #727272;
    width: 10px;
    height: 10px;
    cursor: se-resize;
    position:absolute;
    right: 0;
    bottom: 0;
}

The parent div#box has the CSS property position: relative and by setting div#handle the property position:absolute, we have the ability to position the handle absolutely with respect to its parent.

Also, note the cursor: se-resize property. This instructs the browser to set the cursor to the resize cursor () when the user is over it.

Now, it’s upto to javascript to take over. :wink:

var resizeHandle = document.getElementById('handle');  
var box = document.getElementById('box');  

For resizing, the user would click on the handle and drag it. So, we need to start resizing the moment the user presses and holds on the handle. Let’s setup a function to listen for the mousedown event.

resizeHandle.addEventListener('mousedown', initialiseResize, false);  

the initialiseResize function should do two things:

  1. Resize the box every time the mouse pointer moves.
  2. Listen for mouseup event so that the event listeners can be removed as soon as the user is done resizing.
function initialiseResize(e) {  
    window.addEventListener('mousemove', startResizing, false);
    window.addEventListener('mouseup', stopResizing, false);
}
function startResizing(e) {  
    // Do resize here
}
function stopResizing(e) {  
    window.removeEventListener('mousemove', startResizing, false);
    window.removeEventListener('mouseup', stopResizing, false);
}

To resize the box according to the user’s mouse pointer movements, we’ll be taking the current x and y coordinates of the mouse pointer (in pixels) and change the box’s height and width accordingly.

function startResizing(e) {  
   box.style.width = (e.clientX) + 'px';
   box.style.height = (e.clientY) + 'px';
}

e.clientX gives the mouse pointer’s X coordinate and e.clientY gives the mouse pointer’s Y coordinate

Now, this works. But this would only work as expected if the box is placed in the top-left corner of the page. We’ll have to compensate for the box’s left and top offsets. (position from the left and top edges of the page)

function startResizing(e) {  
   box.style.width = (e.clientX - box.offsetLeft) + 'px';
   box.style.height = (e.clientY - box.offsetTop) + 'px';
}

There you go :smile: We can now resize the box !

https://jsfiddle.net/niranjan94/w8k1ffju/embedded

Continue ReadingBuilding interactive elements with HTML and javascript: Resizing

Working with Absolute Positioning

During the past week, I have done a lot of work for making the feature that allow the users to view the schedule of events according to track and time. The toughest part was to have a headstart to think of the mockup that fulfills this criterion.

After the mockup, I started coding it and realized that I have to add CSS by using Javascript. The frontend needs to calculate the top of each pop-up that appears when the track is hovered and to append the box just below it.

a

The interesting part was to calculate the top each time the element is hovered and to place the box at the right position by using jQuery.

Position Absolute 

The difficulty becomes maximum when we use “position : absolute “. As, it takes the element out of the layer. The element with absolute positioning is difficult to handle when it comes to responsiveness. Here also the pop-overs showing the speakers are to be made with absolute positioning.

The code snippet shows the calculation for exact position of the pop-up box.

$(document).ready(function(){

 $('.pop-box').hide();
 $('.item').hover(function (event) {

 event.preventDefault();
 event.stopPropagation();
 var track = $(event.target);
 var link = track.children(0);
 var offset =$(link).offset();

 var position= offset.top-link.height()-30;
 if( $(window).width()<600){
 var position= offset.top-link.height()-48; 
 }
 if(offset.top){
 
 $('.pop-box').hide();
 var p=$(this);
 $(p).next().show();
 var posY = event.pageY;
 nextOfpop=$(p).next();
 
 var toptrack = position ;

 $(nextOfpop).css({'top':toptrack
                 });

 $(document).mouseup(function (e)
 {
 var container = $(".pop-box");

  if (!container.is(e.target) 
  && container.has(e.target).length === 0 && (e.target)!=$('html').get(0)) 
   {
   container.hide();
   }
   });
  });
 })

This code sets the value of top of the pop-over in the variable position and copy it to toptrack that is passed to CSS to adjust the top dynamically.

Responsiveness for top

I was struggling a whole day to find out the best possible way for the responsiveness of track page. Obviously, the difficult part was the recalculation of top with the screen-size. Currently I have used $window.width() to check the width of screen and adjust the top on mobile. But, it will include more complexity when it is done for other screen sizes rather than mobile.

 if( $(window).width()<600){
 var position= offset.top-link.height()-48; 
 }

The tracks page is ready now with both light and dark theme.

10.png

That’s how the position absolute is handled with jQuery. To remove the complexity, all the CSS except the calculation of top is written with SASS.

Continue ReadingWorking with Absolute Positioning

Building interactive elements with HTML and javascript: Drag and Drop

{ Repost from my personal blog @ https://blog.codezero.xyz/building-interactive-elements-with-html-and-javascript-drag-and-drop }

Traditionally, all interactions in a website has been mostly via form inputs or clicking on links/button. The introduction of native Drag-and-drop as a part of the HTML5 spec, opened developers to a new way of Graphical input. So, how could this be implemented ?

Making any HTML element draggable is as simple as adding draggable="true" as an attribute.

<div id="a-draggable-div" draggable=true>  
    <h4>Drag me</h4>
</div>  

This will allow the user to drag div#a-draggable-div. Next, we need to designate a dropzone, into which the user can drop the div.

<div id="dropzone" ondragover="onDragOver(event)">  
</div>  
function onDragOver(e) {  
    // This function is called everytime 
    // an element is dragged over div#dropzone
    var dropzone = ev.target;

}

Now, the user will be able to drag the element. But, nothing will happen when the user drops it into the dropzone. We’ll need to define and handle that event. HTML5 provides ondrop attribute to bind to the drop event.

When the user drops the div into the drop zone, we’ll have to move the div from it’s original position into the drop zone. This has to be done in the drop event.

<div id="dropzone"  
ondrop="onDrop(event)"  
ondragover="onDragOver(event)"> </div>  
function onDrop(e) {  
    e.preventDefault();
    var draggableDiv = document.getElementById("a-draggable-div");
    draggableDiv.setAttribute("draggable", "false");
    e.target.appendChild(draggableDiv);
}

So, when the user drops the div into the drop zone, we’re disabling the draggable property of the div and appending it into the drop zone.

This is a very basic drag and drop implementation. It gets the job done. But, HTML5 provides us with more events to make the user’s experience even better 1.

Event Description
drag Fired when an element or text selection is being dragged.
dragend Fired when a drag operation is being ended (for example, by releasing a mouse button or hitting the escape key).
dragenter Fired when a dragged element or text selection enters a valid drop target.
dragexit Fired when an element is no longer the drag operation’s immediate selection target.
dragleave Fired when a dragged element or text selection leaves a valid drop target.
dragover Fired when an element or text selection is being dragged over a valid drop target
dragstart Fired when the user starts dragging an element or text selection.
drop Fired when an element or text selection is dropped on a valid drop target.

With these events a little bit of css magic a more user friendly experience can be created like highlighting the drop zones when the user starts to drag an element or changing the element’s text based on its state.

Demo:

https://jsfiddle.net/niranjan94/tkbcv3md/16/embedded/

External Resources:
Continue ReadingBuilding interactive elements with HTML and javascript: Drag and Drop