Addition of new filters for event search

Open Event has an event search provided but it lacked two of the userful filters which will make searching for an event for a user easier than the current ecosystem. In this blog post, I describe how I implemented filtering of events on the basis of CFP status and Ticket Type.

About the issue

Addition of these two filters were subparts of improving the browse events page better. The browse events page currently functions in an optimal way but these improvements make it even better.

How the filters are added

For adding these two filters, it was required that the request sent to server to filter the event must contain ticket type and cfp so that the results from the server can be received. To achieve this, the frontend code needed the following changes:

  1. Passing of request variable into sidebar component present in app/templates/explore.hbs and addition of a clear filter for the same in the same file.e startDate=start_date endDate=end_date location=location ticket_type=ticket_type}
{{explore/side-bar model=model category=category sub_category=sub_category event_type=event_type startDate=start_date endDate=end_date location=location ticket_type=ticket_type}}
{{#if filters.ticket_type}}
  <div class=”ui mini label”>
    {{ticket_type}}
    <a role=”button” {{action ‘clearFilter’ ‘ticket_type’}}>
      <i class=”icon close”></i>
    </a>
  </div>
{{/if}}
  1. Adding UI for both the filters in app/templates/components/explore/side-bar.hbs. Accordion UI is used to achieve this.
  <div class=”item”>
    {{#ui-accordion}}
      <span class=”title”>
        <i class=”dropdown icon”></i>
        {{t ‘Ticket Type’ }}
      </span>
      <div class=”content menu”>
        <a href=”#”
          class=”link item {{if (eq ticket_type ‘free’) ‘active’}}”
          {{action ‘selectTicketType’ ‘free’}}>
          {{t ‘Free’}}
        </a>
        <a href=”#”
          class=”link item {{if (eq ticket_type ‘paid’) ‘active’}}”
          {{action ‘selectTicketType’ ‘paid’}}>
          {{t ‘Paid’}}
        </a>
      </div>
    {{/ui-accordion}}
  </div>
  1. Editing the routes (app/routes/explore.js) to make sure if the request has new filter parameter then it should be sent to server.
if (params.ticket_type) {
      filterOptions.push({
        name : ‘tickets’,
        op   : ‘any’,
        val  : {
          name : ‘type’,
          op   : ‘eq’,
          val  : params.ticket_type
        }
      });
    }
  1. Addition of new request parameter in the controller (app/controllers/explore.js)
queryParams  : [‘category’, ‘sub_category’, ‘event_type’, ‘start_date’, ‘end_date’, ‘location’, ‘ticket_type’],

ticket_type  : null,

if (filterType === ‘ticket_type’) {  this.set(‘ticket_type’, null);
}
  1. Editing the sidebar component to set the value of request parameter when the user interacts with the filter.
hideClearFilters: computed(‘category’, ‘sub_category’, ‘event_type’, ‘startDate’, ‘endDate’, ‘location’, ‘ticket_type’, function() {
    return !(this.category || this.sub_category || this.event_type || this.startDate || this.endDate || this.location || this.ticket_type !== null);
}),

selectTicketType(ticketType) {
  this.set(‘ticket_type’, ticketType === this.ticket_type ? null : ticketType);
},

this.set(‘ticket_type’, null);

Sidebar after the addition of filters.

Resources:

Issue: https://github.com/fossasia/open-event-frontend/issues/3098
Pull Requests:

Ticket Type: https://github.com/fossasia/open-event-frontend/pull/3158
CFS: https://github.com/fossasia/open-event-frontend/pull/3144

Specifying Query Params: https://guides.emberjs.com/release/routing/query-params/

UI Resources for the feature: https://semantic-org.github.io/Semantic-UI-Ember/#/modules/accordion

Continue ReadingAddition of new filters for event search

How to Add Icons or Menus into the PSLab Android App Toolbar

This blog demonstrates how to add different icons like help, play, pause, etc. and/or menu bar in the toolbar of an Android app along with setting their visibilities on the toolbar i.e. to display the icons only when space is available else to add them in the menu. The topic will be mainly explained by taking the example of menus and icons added to the PSLab app.

How to add a menu in a toolbar?

Following are the steps to add a menu or an icon in the toolbar widget of the Android app

  • First, add toolbar widget to the main layout file as follows
<android.support.v7.widget.Toolbar
   android:id="@+id/compass_toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   android:background="?attr/colorPrimary"
   app:popupTheme="@style/AppTheme.PopupOverlay"
   app:title="@string/compass" />

Here, popupTheme is the theme that activates when inflating the toolbar. Usually, it is kept similar to the default theme of the toolbar.

  • Now as the toolbar is ready, we can make the menu that needs to be inflated on the toolbar. For making a menu, make a folder named menu in the resources folder. Now, add a menu resource file in it by giving a proper name and then add the following code
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/compass_help_icon"
       android:icon="@drawable/compass_help_icon"
       android:title="@string/show_axis_help"
       app:showAsAction="always" />
</menu>

A detailed explanation of the above code is as follows:

  1. The <menu>…</menu> covers all the items in the menu. There can be sub-menu and also sub-sub-menu too. To make a sub-menu, use <menu>…</menu> inside the main menu.
  2. The <item> tag inside the menu defines a specific item to be included in the menu. The icon attribute of an item is used to show the icon on the toolbar. The title attribute of an item is used to show the text inside the menu if space isn’t available to show the icon on the toolbar. The showAsAction attribute is used to define the method of an item i.e. how the item should be visible to the user. Following are some of the values that showAsAction attribute can take:
    • always – It is used to show the icon of the item on the toolbar everytime
    • never – It is used to show the item as a text in the menu everytime the activity is opened
    • ifRoom – It is used to show the icon on the toolbar if there is enough space else the item is included in the menu

NOTE: Always give IDs to menu items as they are used to distinctly identify the item in the java code.

Figure 1. Example of menu and icons in toolbar in PSLab app

As shown in figure 1, the first two icons have always value in their showAsAction attribute whereas other items have never values in their showAsAction attribute.

  • Now the layout and the menu are ready to be inflated from the Java code. First, the toolbar needs to be set up from the Java code. So find the toolbar with its id and then write the following line in the code.
setSupportActionBar(mToolbar);
  • Now the toolbar is ready and so the menu can be inflated on it. So, override the following method to inflate the menu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.activity_compass_help_menu, menu);
   return true;
}

Here, the getMenuInflater() method is used to inflate the menu on the toolbar.

  • Now override the onCreateOptionsMenu() method to do the predefined task of selecting the icon or the item from the menu.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
       case R.id.compass_help_icon:
           // Do something
           break;
       default:
           break;
   }
   return true;
}

So, in this way a menu can be made so that the number of items delivered to the user can be increased by using the minimum space possible.

Resources

  1. https://developer.android.com/guide/topics/ui/menus – Android Developers guide on how to make a menu in Android
Continue ReadingHow to Add Icons or Menus into the PSLab Android App Toolbar

Implementing Rotary Knob in PSLab Android App

PSLab android application as we all know has got various instrument such as oscilloscope, logic analyzer, wave generator, etc.. . Although many of  these instrument require redesigning of it’s UI. One such instrument is the  Multimeter. The Multimeter UI required the implementation of the rotary knob as it is also present in an actual Multimeter.Thus this blog is solely on how to implement a Rotary Knob in an Android App.

Figure 1: Showing a basic knob

What is Rotary Knob ?

A Rotary knob is  a customizable selector that replicates the behaviour of a knob with discrete values.The knob is a powerful tool it has a lot of advantages over other radio-buttons, seek bars or other selectors.[1][2]

      • It has an immediate graphical indication of the current value, the number of choices and where the value is in the overall range.
      • Works fine also with few choices, as a multi-state toggle.
      • Swipe gestures allow to change values very quickly, using the entire screen for the gesture, but only a tiny zone of it for the graphics.

Implementation of Rotary Knob in your app[1]

In this blog the rotary knob is implemented using the BeppiMenozzi Knob library[1] as by doing this we don’t have to manually create the extra class for the knob and we don’t have to write the code from scratch.

This blog will give you step by step guide on how to implement this on your app.

        1. In your project level build.gradle file add the following lines of code.
          allprojects {
            repositories {
                   ….
                maven { url "https://jitpack.io" }
                ….
            }
          }
        2. In you app level build.gradle file add the following lines of codes in your dependencies.
          compile 'com.github.BeppiMenozzi:Knob:1.9.
        3. Minimal code :-
          This contains the minimum number of lines of code for knob

          xmlns:app="http://schemas.android.com/apk/res-auto"
          ...
          <it.beppi.knoblibrary.Knob
                  android:layout_width="64dp"
                  android:layout_height="64dp"
                  android:id="@+id/knob"
                  app:kNumberOfStates="6"
           />

          Java listener-

          xmlns:app="http://schemas.android.com/apk/res-auto"
          Knob knob = (Knob) findViewById(R.id.knob);
          knob.setState(firstState);
          knob.setOnStateChanged(new Knob.OnStateChanged() {
                  @Override
                  public void onState(int state) {
                  // do something
                  }
              });

          This java method gives the user the position of the tip of theknob.
          Also there are various other advantages of using this library.

              • The Knob is completely customizable. The many customizable attributes can all be set both via xml file, and programmatically.
              • This  page gives the list of all the methods for customizing a knob.

           

        4.  Implementing a simple knob app
          tv= (TextView)findViewById(R.id.tv);
          Knob knob = (Knob) findViewById(R.id.knob);
          knob.setState(0);
          knob.setOnStateChanged(new Knob.OnStateChanged() {
             @Override
             public void onState(int state) {
                 // do something
                 tv.setText(String.valueOf(state));
             }
          });

Now let us see the implementation of this simple app

Figure 2: showing basic knob implementation in android

So this is how we can implement a rotary knob in any Android Application.

Resources:

 

 

 

Continue ReadingImplementing Rotary Knob in PSLab Android App

Implementing Carousel Slider in PSLab Android App

This blog is a demonstration for creating a Carousel Picker in Android by taking an example of the Carousel Picker made in PSLab Android app under PR #1007. Some improvement to this would be to add custom animation to the ViewPager and adjusting the ViewPager sliding speed. So first let’s start with the basics and terminology of Carousel.

What is Carousel?

Carousel according to the dictionary means roundabout or merry-go-round. The term was mainly used for the traditional amusement ride of a merry-go-round in amusement parks with seats of horses. The same is the working of Carousel View in Android. It gives a smooth sliding effect to slide between a variety of options available.

How to implement Carousel View in the app?

Following are the steps to implement a basic Carousel View in the app. Further effects and upgrades can be given as per the need.

  • The first step is to add jitpack to your app’s gradle file
maven { url 'https://jitpack.io '}
  • Now add a library dependency in your project level gradle file
compile 'com.github.Vatican-Cameos:CarouselPicker:v1.0

The above dependency uses the View Pager and Gesture Detector functionality provided by Android. The Gesture Detector class detects the swipe gesture made by the user and the View Pager highlights the relevant label in the Carousel box according to the swipe done i.e left or right.

  • Now Carousel Picker is ready to be added directly to layouts. So, add the Carousel by adding the following layout code at a proper section in layouts file.
<in.goodiebag.carouselpicker.CarouselPicker
	android:id="@+id/carouselPicker"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:layout_marginTop="20dp"
	android:layout_marginBottom="20dp"
	android:background="#DDD"
	apps:items_visible="three" />

Here, the items_visible is used to provide the Carousel Picker with the number of max items to be seen at a time on screen where only one item will be in focus. Other items are adjusted on the side and can be viewed by scrolling.

  • Now as we have implemented the layouts, so now’s the time to set adapter and resource type for Carousel to hold in Java files. First, find the Carousel View with its id.
CarouselPicker carouselPicker = findViewById(R.id.carouselPicker);
  • Now set a list of items to be added in the Carousel Picker. The items can be both images and texts.
List<CarouselPicker.PickerItem> items = new ArrayList<>();

To add images :

items.add(new CarouselPicker.DrawableItem(R.mipmap.ic_launcher));

To add texts/strings :

items.add(new CarouselPicker.TextItem("Example", 10));

Here, the integer that is added after the text indicates the size in sp of the text that is to be displayed in Carousel View.

  • Now after creating a list of items, make an adapter which provides this list of information to Carousel Picker.
CarouselPicker.CarouselViewAdpater adapter = new CarouselPicker.CarouselViewAdpater(this, items);
  • Now set the adapter for the Carousel View :
carouselPicker.setAdapter(adapter);
  • To dynamically add items to the Carousel View, simply change the list of items in the list provided to the adapter and then use
adapter.notifyDataSetChanged();
  • Now to change the functionality of the app with every Carousel item, implement the onPageChangeListener as Carousel View implements ViewPager class.
carouselPicker.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        	@Override
        	public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        	}

        	@Override
        	public void onPageSelected(int position) {
        	}

        	@Override
        	public void onPageScrollStateChanged(int state) {
          }

Following GIF shows how Carousel View looked after implementation in PSLab app. Each option provided in the view was used to provide user with a different channel selection mode.

Figure 1. GIF of implemented Carousel View in PSLab app

So in this way, a Carousel Picker or Carousel View can be implemented in the app. Further functionalities of animations, mirroring, shadow effect, all can be done with just minor changes in the above code. And to fully customize the look of the Carousel or to enable infinite scrolling feature, a local Carousel Picker can be implemented by just making a custom adapter and a class that extends ViewPager class. Below are the resources to implement both custom and dependency based Carousel View.

Resources

  1. https://www.youtube.com/watch?v=sTJm1Ys9jMI – Youtube Video for dependency based Carousel View
  2. https://www.youtube.com/watch?v=4ct0oPf_u2o – Youtube Video for implementing infinite scrolling
  3. http://www.codexpedia.com/android/android-carousel-view-using-viewpager/ – An article to implement custom Carousel View

 

 

 

 

 

Continue ReadingImplementing Carousel Slider in PSLab Android App

Implementing Card View in PSLab app

Card View was announced by Google in I/O ‘14 conference. Although it started a bit slow, but now we can see most of the apps like Snapchat, Google, Facebook, etc. using this widget. So, this blog is solely contributed on how to implement Card View in your own app by taking example of PSLab application.

What is Card View ?

CardView is a view container or ViewGroup that inherits its nature from FrameLayout which further inherits from ViewGroup itself. The only thing that separates a CardView from any other ViewGroups is its nature to behave like a card, more specifically the shadow and rounded corners. The basic customization that a CardView provides includes CornerRadius, Elevation, MaxElevation, ContentPadding, CompatPadding, PreventCornerOverlap, and a dedicated CardBackgroundColor or say Card Background which is the most necessary feature for a card to look cool.

Step by Step description how CardView was implemented in PSLab

  • First step is to add dependencies in your project as widgets like Card View, Recyclerview, etc. are not included in a common repository of widgets provided by Google.

App level dependency :

compile 'com.android.support:cardview-v7:26.0.0'
compile 'com.android.support:recyclerview-v7:+'

If you are using Android Studio 3.0+ than add the following dependency instead of above :

implementation 'com.android.support:cardview-v7:26.0.0'
implementation 'com.android.support:recyclerview-v7:27.1.1'
  •  Now we can use Card View widget in our app. So, first make add card view in layout section like this :
<android.support.v7.widget.CardView
    	android:id="@+id/card_view"
    	android:layout_width="match_parent"
    	android:layout_height="@dimen/total_height_card"
    	android:layout_gravity="center"
    	android:layout_margin="@dimen/card_margin"
    	card_view:cardCornerRadius="@dimen/card_radius">
 </android.support.v7.widget.CardView>

These are the basic attributes that are used while declaring a card view. Other possible attributes can be :

  1. Elevation – Used to elevate card to give a depth effect
  2. MaxElevation – Used to give constraint to the depth effect
  3. ContentPadding – Used to provide padding between content and the card
  4. PreventCornerOverlap – To prevent different corners to overlap as shown in figure 1.

Figure 1. Image showing corner overlapping in CardView

  • Now to set the objects inside the Card View, mostly RelativeLayout is preferred as it gives the freedom to place objects in reference of others whereas LinearLayout provides freedom to place them in only one direction. Other layouts such as FrameLayout, Tables, etc. can be used as per the need of the app.
  • Now we will create a layout that will hold all the cards using RecyclerView.
<android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
  • Now after setting the layouts, it’s time to make adapter which inflates the information in the cards which is then represented using RecyclerView.
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.Holder> {

	private List<ApplicationItem> applicationList;
	private final OnItemClickListener listener;
	/**
 	* View holder for application list item
 	*/
	public class Holder extends RecyclerView.ViewHolder {

    	TextView header, description;
    	ImageView applicationIcon; //Background Image

    	public Holder(View itemView) {
        super(itemView);
        this.header = itemView.findViewById(R.id.heading_card);
        this.description = itemView.findViewById(R.id.description_card);
        this.applicationIcon = itemView.findViewById(R.id.application_icon);
    	}

    	public void setup(final ApplicationItem applicationItem, final OnItemClickListener listener) {
      header.setText(applicationItem.getApplicationName());
      description.setText(applicationItem.getApplicationDescription());
      applicationIcon.setImageResource(applicationItem.getApplicationIcon());
         }
	}

	public ApplicationAdapter(Context mContext, List<ApplicationItem> applicationList, OnItemClickListener listener) {
    	this.mContext = mContext;
    	this.applicationList = applicationList;
    	this.listener = listener;
	}

     @Override
	public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
    	View itemView = LayoutInflater.from(parent.getContext())
            	.inflate(R.layout.application_list_item, parent, false);
    	return new Holder(itemView);
	}

Following is the detailed explanation of each and every method :

  1. Holder(View ) – As name suggests, it holds all the items that are included in a single card together
  2. setup() – This method can contain any number of parameters as per requirement. It basically sets the data in the views in the card
  3. ApplicationAdapter() – Constructor
  4. onCreateViewHolder() – It inflates the layout containing CardView as soon as the data gets ready to be fed in it
  • Now as adapter is ready, we can declare RecyclerView in Java code to implement CardView. The main reason to use RecyclerView is that it provides the feature of scrollability so that a number of cards can be adjusted on the screen. ScrollView can also be used but it slows down the app as it tries to load all the card at once rather than loading cards as per use like RecyclerView.
RecyclerView listView = view.findViewById(R.id.applications_recycler_view);
    	RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(context, rows);
    	listView.setLayoutManager(mLayoutManager);
    	listView.setItemAnimator(new DefaultItemAnimator());
    	listView.setAdapter(applicationAdapter);

Here, we have used GridLayoutManager to use grids along with RecyclerView. It is optional and can be used as per requirement. Also, before setting adapter, fill the adapter with relevant data or else no card will be seen in actual app.

  • Now the app is ready to be built and tested on mobile device. This is how it looks in the PSLab application after implementing the above guide :

Figure 2. Screenshot of CardView implemented in PSLab app

So, in this way great user experience can be given by using this very basic widget. But great attention should be given while designing the objects inside the card as the selection and position of the objects is what makes the card look good. Objects used in making cards for PSLab very well suited the app and so are designed like that. Practice should be done by taking reference of some very good apps like Snapchat, Google, etc. and from Material Designs provided by Google before implementing them in actual project.

Resources

  1. https://www.androidhive.info/2016/05/android-working-with-card-view-and-recycler-view/ – This article gives a better practice by implementing a real world example
  2. https://developer.android.com/reference/android/support/v7/widget/CardView – Official documentation by Google on CardView
  3. https://developer.android.com/guide/topics/ui/layout/recyclerview – Official documentation by Google on RecyclerView

Continue ReadingImplementing Card View in PSLab app

Implementing search bar in PSLab app

PSLab offers a large range of functions with a large field of applications. This results in the long access path to certain information and functionality in the app, which affects the user experience (UX) negatively. In this blog post, I will show how the UX in Android applications with many functions can be improved by implementing a ‘Search Bar’. Further, I have created a screencast that follows the step-by-step description shown in this blog post [1].

Search Bar is the functionality which can be seen nowadays in almost all the apps. It is a handy widget for users to navigate the app. PSLab’s Android app was lacking this functionality and so I added it using an external library from Mirrajabi called ‘search-dialog’ [3]. I decided to use this library as it provides a search bar with built-in functionality of highlighting the text that’s selected or written down in the ‘Edit Text’ field by the user and also it overlays on the screen which provides a good user experience rather than other search bars which overlap on the text provided on the screen with a ListView. Further working with this dependency was easier than working with others as it seems well designed.

The Search Bar was added in the Saved Experiments section which contains a lot of default experiments along with their respective manuals. The search bar was intended to provide the user with a greater UI so that they don’t need to navigate through sections every time to find an experiment.

This blog is a step by step guide on how to implement it in any app.

  1. First, add dependencies in the gradle at both project level and app level. By adding these dependencies, we don’t need to worry about writing code for how the Search Bar will filter searches and how it will be placed on the screen.

App Level :

'com.github.mirrajabi:search-dialog:1.1'

Project Level :

maven { url "https://jitpack.io" }
  1.  Create a SearchModel class which will help to carry out the search operations.
public class SearchModel implements Searchable {

	private String mTitle;

	public SearchModel(String mTitle) {
    	this.mTitle = mTitle;
	}

	public void setTitle(String mTitle) {
    	this.mTitle = mTitle;
	}

	@Override
	public String getTitle() {
    	return mTitle;
	}
}

The SearchModel class helps to communicate with the filtered search results by returning the string which is selected:

  • SearchModel(String string) – It is a default constructor
  • setTitle(String string) – It is a method used to set the string provided in the search results
  • getTitle() – It is also a method to get the string selected by the user from the filtered search result provided
  1.  Now provide some data which needs to be searched using an ArrayList or by using StringArrays and then converting it to Search Model Object.
private ArrayList<SampleSearchModel> createSampleData(){
        ArrayList<SampleSearchModel> items = new ArrayList<>();
        items.add(new SampleSearchModel("First item"));
        items.add(new SampleSearchModel("Second item"));
        items.add(new SampleSearchModel("Third item"));
        items.add(new SampleSearchModel("Fourth item"));

        return items;
    }
  1.  At last add the constructor in MainActivity to make the search bar.
SimpleSearchDialogCompat(Context context, String title, String searchHint, @Nullable Filter filter, ArrayList<T> items,
SearchResultListener<T> searchResultListener)

All the parameters can be given according to requirement. The function of each and every parameter are as under :

  • Context – Provide context of the current activity
  • String title – To provide title to Search Bar
  • String searchHint – To provide hint text to the user
  • Filter – To provide any additional filters to the search made by the user
  • ArrayList<T> – To provide data that can be searched
  • SearchResultListener<T> – The method which handles what to do when a user clicks on the filtered searches provided

Let’s try to search for the Piezo Buzzer and UltraSonic Range Finder Experiments in the Search Bar :

Figure 1. GIF of implemented Search Bar

So, in this way, I have implemented the Search Bar functionality in the PSLab application. One last note that try to practice this widget before implementing it in the main project as it requires some practice of filters as per requirements and also its location needs to be defined as per the requirement of an organization as it can be placed anywhere from the main screen to the toolbar to navigation drawer. Below are some of the useful resources to get best practice.

Resources

  1. https://youtu.be/QyqbRHt1NUE – How to make a search bar like above (By – Harsh Patel (me))
  2. https://github.com/mirrajabi/search-dialog – This is the GitHub Page of the library which I used in making an attractive screen overlaying search bar rather than the old one with the list view placed in the toolbar
Continue ReadingImplementing search bar in PSLab app

Open Event Server Ticket PDF: Where and Where-not to use static frame in xhtml2pdf

One among the very important features of Open Event Server project is the tickets sales feature, where a user can buy a number of different tickets for a number of people after which he is given a link to download the ticket pdf. However, an issue concerning our Open Event Server project was that if a buyer bought different tickets at a time with different individual ticket holders, all tickets contained the same name, type and QR-Code, which in no way was acceptable since tickets and holders were different.

We use the xhtml2pdf facility in order to convert an html to pdf. An xhtml2pdf facility helps us in converting HTML contents into PDF without the use of browser ‘print’ facility. In order to do this, we use the help of pages and frames, pages being the page of the PDF document, while a frame being that part of area within the page where the contents get stored.

What is a PDF and HTML?

The basic understanding of a PDF and an HTML is that, a PDF or Portable Document Format has layout such that it is measured in terms of specific width and height. However, for an HTML or Hyper Text Markup Language, we do no not have those specific widths and heights. Rather an HTML’s width depends on a person’s device of view and height can be infinitely long as desired.

In terms of xhtml2pdf relation with pages and frames layout, we can identify with this diagram:

+-page———————+
|                                    |
|  +-content_frame-+  |
|  |                          |    |
|  |                          |    |
|  |                          |    |
|  |                          |    |
|  +———————+   |
|                                    |
+—————————-+


The stated issue was due to static frame in xhtml2pdf.

What is that you ask?

Static frames vs Content frames
xhtml2pdf uses the concept of Static Frames to define content that remains the same across different pages (like headers and footers), and uses Content Frames to position the to-be-converted HTML content.

Static Frames are defined through use of the @frame property -pdf-frame-content. Regular HTML content will not flow through Static Frames.

Content Frames are @frame objects without this property defined. Regular HTML content will flow through Content Frames.(xhtml2pdf documentation)

So, the basic idea of the use of  -pdf-frame-content  was to make the contents of the pdf static i.e. without having to continuously change alignments of the page. It made the whole pdf stay static.

This actually caused the whole pdf content to stay constant, event while the loop was going over different name, QR-code and ticket-name values. That means the first loop content stayed over even with changes in values.

Just a simple fix of not making the frame static was the solution.

Here is a few insight of what we had before that was causing the issue:

 <style>
        @page {
            size: a4 portrait;
            background-image: url('{{ base_dir }}/static/data/ticket-trans-
                                  notext.png');
            margin: 0;

            @frame col1_frame {             /* Content frame 1 */
                left: 80pt;  top: 30pt;
                height: 250pt; width: 300pt;
                -pdf-frame-content: main_content;
            }

            @frame qrcode {
                left: 455pt;  top: 50pt;
                width: 100pt; height: 120pt;
                -pdf-frame-content: qr_code;
            }
            @frame number_frame {
                 left: 455pt;  top: 25pt;
                width: 100pt; height: 30pt;
                -pdf-frame-content: number_content;
            }


             @frame col2_frame {
                left: 440pt; top: 170pt;
                -pdf-frame-content: personal_content;
            }
        }


Here,
main_content, qrcode, personal_content and number_content? are simply the class you want to make static.
The following was done to fix it:

 <style>
        @page {
            size: a4 portrait;
            background-image: url('{{ base_dir }}/static/data/ticket-trans-
                                  notext.png');
            margin: 0;

            @frame col1_frame {             /* Content frame 1 */
                left: 80pt;  top: 30pt;
                height: 250pt; width: 300pt;
            }

            @frame qrcode {
                left: 455pt;  top: 50pt;
                width: 100pt; height: 120pt;
            }
            @frame number_frame {
                 left: 455pt;  top: 25pt;
                width: 100pt; height: 30pt;
                -pdf-frame-content: number_content;
            }


             @frame col2_frame {
                left: 440pt; top: 170pt;
            }
        }



But the main question was, ‘where and where-not to use static frame’.
So the simple answer to that is, when you want the contents to stay exactly the same over the different pages of the pdf (for example the company logo or the administrator signature, etc), then you can happily get on with -pdf-frame-content. i.e:

          -pdf-frame-content: <class_name>


If not, or you need to loop over different values, then use Content frames.

Also, for more detailed understanding of PDF and HTML pages and frames, we have this good documentation written about it here: https://github.com/xhtml2pdf/xhtml2pdf/blob/master/doc/source/format_html.rst#static-frames-vs-content-frames

Continue ReadingOpen Event Server Ticket PDF: Where and Where-not to use static frame in xhtml2pdf

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