Categories
Technology

My take on Reliance Jio4 min read

Reliance Jio offers unlimited free calls and 4G LTE data till December 2016. I have recently got the Jio sim card, of course to get free 4G internet ???? .

Speed

This Economic times article says Jio offers 17.34 Mbit/s down speed.

But I get about 4 – 7 Mbps download speed on average when in full range. Speed measured with fast.com

I was very happy about this until I searched the internet for 4G LTE speeds.

Data speeds of LTE (Theoretical)
LTE
Peak download 100 Mbit/s
Peak upload 50 Mbit/s

Stolen from – Wikipedia.org

OK there is nothing here to be unhappy about, everybody knows that’s not going to happen. But let’s look at the average speeds in other countries.

Average speeds of 4G in other countries – 
UK  16 – 25 Mbit/s
USA 9 – 16 Mbit/s

Stolen from – Opensignal.com

Hmmm… ????

Maybe Opensignal results from india would also show similar results and the speed may vary in different parts of India.

So the question is am I happy with the speeds that I get?

A – I am, very much.

Why Jio calls are free?

The answer is they are not. Jio offers unlimited calls for a fixed charge and does not charge you by duration of the call like other providers.

For example if we look at their 149 plan, it offers 400 MB of 4G data and unlimited Local/STD calls for a period of 28 days from charging.

After 28 days if you do not recharge, the calls are no more free.

But when compared to other providers who charge separately and too much for data, calls and sms, the Jio offer looks pretty good.

How does Jio calls work?

Jio uses VoLTE standard for making calls. Unlike other providers Jio only has 4G LTE networks plus their wifi network as given in their website.

So calls pass through the LTE network following a protocol known as VoLTE (Voice over LTE). But other providers use 2G network with GSM protocol to make voice calls.

Essentially the voice is broken down and send as data packets.

Any LTE enabled phone can can make voice calls with Jio. But the phone must have the necessary software that supports the VoLTE protocol. Your phone may already have this or you can get it from doing an OS upgrade.

Jio provides the Jio voice app for phones that do not support VoLTE.

Does Reliance sent our personal data to ad networks?

Anonymous India Claims That Reliance Jio Is Sharing Call Data With Advertisers.

The above article says that Anonymous India, a hacker group claimed Jio apps are sending user call data to servers in US and Singapore and also to an ad network.

The group has also made more claims and Reliance has answered the concerns.

Anonymous post – Told truth with facts about Reliance Jio Chat app, targeted by Reliance Media Director.

Reliance reply – A statement by Reliance Jio Infocomm Ltd.

Any provider can view or sell user data unless it is encrypted at a higher level because it just passes through their gateways. But it would be illegal to do so without mentioning it in their terms and conditions.

 But the privacy policy in Jio website says

Improving your experience while using our services by presenting advertising, products and offers tailored to you;

And in the collection of information section it says

Usage logs/Server logs/Cookies which may contain details of your personal or sensitive personal information.

Conclusion : Hmmm… ????

Unlimited at night

No, Jio does not offer unlimited internet through out the night. It’s just from 2 am to 5 am.  We get unlimited internet for 3 hours a day, but at that part of the day when we least need it. Thank you Mr. Ambani ????.

 Rates

And finally Jio offers its services at the cheapest rates India has ever seen. So what are you waiting for go get it, at least when everything is free. Prove your Indian-ness ???? .

Categories
Programming

Styling HTML forms 23 min read

In a previous post we looked at styling HTML forms. In this one let’s try to take it further and mess around with it.

What are we going to do?

The aim is to add placeholder text to text inputs. If the element is not in focus we want to show only the placeholder text and hide the label text. But if in focus we want to hide the placeholder text and show the label text.

If that explanation didn’t work, here is a working example –

See the Pen Styling HTML forms 2 by hrishikesh mk (@avastava) on CodePen.0

We can add this effect with a few lines of extra javascript. The javascript in the  previous post looked like this –

var inputfade = document.querySelectorAll('.fi input,.fi select,.fi textarea');
var ifln = inputfade.length;
 
function input_fade(elem, on) {
  var span_elem = elem.parentNode.getElementsByTagName('span');
  if (span_elem.length) {
    span_elem[0].style.color = on ? 'rgb(0, 188, 215)' : '#000';
  }
}
for (var i = 0; i < ifln; i++) {
  inputfade[i].onfocus = function() {
    input_fade(this, true);
  }
  inputfade[i].onblur = function() {
    input_fade(this, false);
  }
}

It is to be noted that the desired effect works only with text inputs or elements that have the placeholder property. Ex – input[type=”text”],[type=”password”],[type=”number”], textarea element.

We have to create a collection of elements containing input elements ( excluding the types submit, checkbox and radio ) and textarea elements.

So let’s create a function which would help us identify the required elements. The function takes an element as input and tells us whether it is a required element or not.

function is_text_input(elem) {
  el_name = elem.nodeName.toLowerCase();
  el_type = elem.getAttribute('type');
  if ((el_name == 'input' && el_type != 'checkbox' && el_type != 'radio' && el_type != 'submit') || el_name == 'textarea') {
    return true;
  }
  return false;
}

Upgrading previous code

We need to add place holders for the input elements. So inside the for loop we add the following code

var elem = inputfade[i];
var span_elem = elem.parentNode.getElementsByTagName('span')[0];
if (is_text_input(elem)) {
  elem.setAttribute('placeholder', span_elem.innerHTML);
  if (!elem.value) {
    span_elem.style.opacity = '0';
  }
}

We take the label text and set it as the placeholder after checking if the element is of the required type. The label text is also hidden by setting the opacity property to zero. We are using the opacity property instead of display: none so that we can animate it using css transitions.

We used the input_fade function in the loop to change color of label text on focus. We have to slightly modify this function so that on focus the label text of the element becomes visible. But on blur if the value of the input field is empty we have to hide the label text and show the placeholder text instead.

function input_fade(elem, on) {
  var span_elem = elem.parentNode.getElementsByTagName('span')[0];
  if (span_elem) {
    span_elem.style.color = on ? 'rgb(0, 188, 215)' : '#000';
  }
  if (is_text_input(elem)) {
    if (on) {
      elem.setAttribute('placeholder', '');
      span_elem.style.opacity = '100';
    } else {
      if (!elem.value) {
        elem.setAttribute('placeholder', span_elem.innerHTML);
        span_elem.style.opacity = '0';
      }
    }
  }
}

 

CSS

Our aim was to create a beautiful form, but for this one to look good we need to add some more lines of code.

Styling placeholder text

The placeholder text should look the same as our label text.

::-webkit-input-placeholder {
    color: black;
    font-size: 17px;
    font-weight: 600;
}
:-moz-placeholder {
    /* Firefox 18- */
    
    color: black;
    font-size: 17px;
    font-weight: 600;
}
::-moz-placeholder {
    /* Firefox 19+ */
    
    color: black;
    font-size: 17px;
    font-weight: 600;
}
:-ms-input-placeholder {
    color: black;
    font-size: 17px;
    font-weight: 600;
}

Source – CSS Tricks

Adding a fading effect

Add this line of code to label text element and your beautiful form is ready. 🙂

transition: opacity 0.5s;
Categories
Programming

Creating a Javascript form validation plugin8 min read

After my HTML Form designs are complete the next problem was to validate the input data before sending it to the servers. I don’t use Jquery or any other javascript frameworks. Also i did not find the inbuilt browser validation working well with the user interface i had in mind. So i had to come up with a new “Javascript form validation plugin” in pure vanilla javascript.

OK maybe i should have named it better.

Let’s get started

So where do i start ?

Here are the thing i wanted it to do

  • Set min, max and other properties on the input element and the plugin should check if the input text satisfies the conditions
  • Show an error message with a user recognizable field name and reason why it failed the test.
  • Scroll to the element which broke the rule on submit.
  • Do not submit data if no changes are made in an edit data form.
  • Generate a JSON string from the form data.

I am no expert in javascript but it seemed simple and i had to give it a try.

So i decided to add 2 custom attributes to my input elements.

  • data-sname: A replacement for the name attribute for inputs. This is for the servers to understand what field the data should be inserted to. Ex – If it is the username field data-sname attribute would be “username”.
    <input data-sname="username" />
    
  • data-lname: A field name that the end user would understand. Ex – If any required field was left blank, the error message would be {data-lname of elem} is required.
    <input data-lname="username" data-sname="username" />
    

To start with let us add 3 rules

  1. min – Min value of the input.
  2. max – Max value of the input.
  3. required – whether the field is mandatory.

More rules can be added to improve upon our “Javascript form validation plugin”.  Yup SEO.

Here is the form we have created in this article with our new found attributes added.

<form id="add_form" class="fiform" novalidate >
  <h1>New User</h1>
  <div class="fi" >
    <label>
      <span>User Type</span>
      <select id="user_type" data-lname="User Type" required data-sname="user_type" >
        <option value="1" >Single</option>
        <option value="1" >Team</option>
      </select>
    </label>
  </div>
  <div class="fi" >
    <label>
    <span>Username</span>
    <input id="username" required min="2" max="50" data-sname="username" data-lname="Username" />
    </label>
  </div>
  <div class="fi" >
    <label>
    <span>Password</span>
    <input id="password" type="password" required min="6" max="50" data-sname="pass" data-lname="Password" />
    </label>
  </div>
  <div class="fi" >
    <label>
    <span>Address</span>
    <textarea id="add" required min="6" max="50" data-sname="addr" data-lname="Address" ></textarea>
    </label>
  </div>
  <div class="fi" >
    <label>
    <input type="checkbox" checked data-sname="notify" />
    <span>Recieve Notifications</span>
    </label>
  </div>
  <div class="fi" >
    <label>
    <input type="submit" value="Add" id="submit" />
    </label>
  </div>
</form>

Javascript

Let us create a validator object.

var validator = function(elem) {
    this.form = elem;
    this.error = [false];
    this.qs = '';
    this.result = {};
    this.changed = false;
    this.changes = [];
    this.check_changes = false;
}

It takes the form element which has to be validated as input.

Now let us add the functions that would validate the input.

var validator = function(elem) {
  this.form = elem;
  this.error = [false];
  this.qs = '';
  this.result = {};
  this.changed = false;
  this.changes = [];
  this.check_changes = false;
  this.valid_input = {
    'min': function(input, val, type) {
      if (type == 'number') {
        if (parseFloat(input) < val) {
          return [false, 'Min value of {fieldname} is ' + val];
        }
      } else {
        if (input.length < val) {
          return [false, 'Min length of {fieldname} is ' + val];
        }
      }
      return [true];
    },
    'max': function(input, val, type) {
      if (type == 'number') {
        if (parseFloat(input) > val) {
          return [false, 'Max value of {fieldname} is ' + val];
        }
      } else {
        if (input.length > val) {
          return [false, 'Max length of {fieldname} is ' + val];
        }
      }
      return [true];
    },
    'required': function(input, val, type) {
      if (!input.length) {
        return [false, '{fieldname} is required'];
      } else {
        return [true];
      }
    }
  };
}

The validation functions take 3 inputs

  1. The inputted value.
  2. The value against it has to be checked.
  3. The type of the input element.

The functions return an array. Array key position 1 gives the validity of the input against the condition provided as Boolean. Position 2 gives the error message if any as string.

Now lets add a message box to show the error message.

if (document.getElementById('form_err')) {
  this.emsg = document.getElementById('form_err');
} else {
  this.emsg = document.createElement('div');
  this.emsg.style.padding = '10px 20px';
  this.emsg.id = 'form_err';
  this.emsg.style.background = 'rgb(0, 0, 16)';
  this.emsg.style.color = 'white';
  this.emsg.style.fontSize = '16px';
  this.emsg.style.position = 'absolute';
  this.emsg.style.zIndex = '100';
  this.emsg.style.display = 'none';
  this.emsg.style.top = '10px';
  this.emsg.style.left = '10px';
  this.emsg.style.opacity = '1';
  this.emsg.style.transition = 'opacity 1s';
  this.emsg.style.height = 'auto';
  this.emsg.style.borderRadius = '3px';
  this.emsg.style.boxSizing = 'border-box';
  var pointer = document.createElement('div');
  document.body.appendChild(this.emsg);
}

We also need a function to show this message box.

this.showerr = function(msg, input) {
  this.emsg.innerHTML = msg;
  this.emsg.style.display = 'inline-block';
  this.emsg.style.position = 'fixed'
  this.emsg.style.opacity = '1';
  setTimeout(function() {
    this.emsg.style.opacity = 0;
  }.bind(this), 5000);
  setTimeout(function() {
    this.emsg.style.display = 'none';
    this.emsg.style.position = 'absolute'
  }.bind(this), 6000);
};

And a scroll to element function

this.scrollt = function() {
  var scroll_speed = 15;
  if (this.left != this.leftlimit) {
    if (this.left < this.leftlimit) {
      this.left += scroll_speed;
    } else {
      this.left -= scroll_speed;
    }
  }
  if (this.top != this.toplimit) {
    if (this.top < this.toplimit) {
      this.top += scroll_speed;
    } else {
      this.top -= scroll_speed;
    }
  }
  window.scrollTo(this.left, this.top);
  this.animator = requestAnimationFrame(this.scrollt.bind(this));
  if ((this.top - this.toplimit) > -scroll_speed && (this.top - this.toplimit) < scroll_speed) {
    cancelAnimationFrame(this.animator);
  }
};

Before that we need a function that would return the value of a given element regardless of its type.

function multi_select(sel, string) {
  var opts = [],
    opt;
  for (var i = 0, len = sel.options.length; i < len; i++) {
    opt = sel.options[i];
    if (opt.selected) {
      opts.push(opt.value);
    }
  }
  return (string) ? opts.join() : opts;
}
get_val = function(el) {
  var node_type = el.nodeName.toLowerCase();
  if (node_type != 'input' && node_type != 'select' && node_type != 'textarea') {
    return el.innerHTML;
  }
  if (node_type == 'select' || (node_type == 'input' && el.type != 'checkbox') || node_type == 'textarea') {
    if (el.hasAttribute('multiple')) {
      return multi_select(el, true);
    }
    return el.value.trim();
  } else if (el.type == 'checkbox') {
    return (el.checked) ? 1 : 0;
  }
  return '';
}

Now the validate function

this.validate = function(no_same) {
  var input = [];
  var inputlen = 0;
  var childrenall = this.form.getElementsByTagName('*');
  for (var i = 0, q = childrenall.length; i < q; i++) {
    if (childrenall[i].hasAttribute('data-sname')) {
      if (childrenall[i].hasAttribute('data-active')) {
        if (childrenall[i].getAttribute('data-active') == 'true') {
          input.push(childrenall[i]);
          inputlen++;
        }
      } else {
        input.push(childrenall[i]);
        inputlen++;
      }
      if (childrenall[i].hasAttribute('data-init')) {
        this.check_changes = true;
        if (childrenall[i].getAttribute('multiple') != null) {
          if (childrenall[i].getAttribute('data-init') != multi_select(childrenall[i]).join()) {
            if (!this.changed) {
              this.changed = true;
            }
            this.changes.push(childrenall[i].getAttribute('data-lname').toLowerCase());
          }
        } else {
          if (childrenall[i].getAttribute('data-init') != get_val(childrenall[i])) {
            if (!this.changed) {
              this.changed = true;
            }
            this.changes.push(childrenall[i].getAttribute('data-lname').toLowerCase());
          }
        }
      }
    }
  }
  if ((this.check_changes && !this.changed) || inputlen == 0) {
    this.showerr('No changes made');
    return [false];
  }
  for (var i = 0, q = inputlen; i < q; i++) {
    for (rule in this.valid_input) {
      if (this.valid_input.hasOwnProperty(rule)) {
        if (input[i].hasAttribute(rule) && (input[i].required || input[i].value != '')) {
          var er_check = this.valid_input[rule](get_val(input[i]), input[i].getAttribute(rule), input[i].type);
          if (!er_check[0]) {
            this.left = this.scrollp.scrollLeft;
            this.top = this.scrollp.scrollTop;
            this.toplimit = input[i].offsetTop - 50;
            this.leftlimit = input[i].offsetLeft - 50;
            this.animator = requestAnimationFrame(this.scrollt.bind(this));
            input[i].focus();
            this.showerr(er_check[1].replace('{fieldname}', input[i].getAttribute('data-lname')), input[i]);
            return [false, input[i]];
          }
        }
      }
    }
    this.result[input[i].getAttribute('data-sname')] = encodeURIComponent(get_val(input[i]));
    if (this.changes.length) {
      this.result['changes'] = this.changes.join();
    }
  }
  return [true, this.result];
}

The function loops through all elements of the given form and creates an array of elements which has an attribute of data-sname.

As you can see if an attribute of data-init is set to an element, the current value of the element is checked against the value of this attribute to see if any changes were made.

On error our validator shows a message and focuses on the element which broke the rule. Finally if no errors are found it returns an object with data-sname as key and value of element as value.

Now let’s put our validator to work

document.getElementById('add_form').onsubmit = function(e) {
  e.preventDefault();
  var val = new validator(this).validate();
  if (!val[0]) {
    return;
  }
  alert(JSON.stringify(val[1]));
}

The returned object is converted to a JSON string, and is ready to be send to our servers for further validation.

Download validator.js

You can download the js file from the above link and use it as shown in  code above.

Here is a working example

See the Pen XjzRrg by hrishikesh mk (@avastava) on CodePen.0