Categories
Programming

Random color generator in javascript2 min read

If you ever tried to create HTML or SVG graphs, it is most likely that you have asked google the question How to generate random colors in javascript? , because I for sure did ???? .

Maybe you have searched it for some other reason. To create some cool UI or something, or maybe to irritate the user with stupid colors ???? .

If you have never searched it or thought about it, well why don’t you go ahead and try it now, it’s free after all.

There are plenty of resources in the internet that would help you get the job done. But here is my little experiment.

Where to start?

I want a function that would take the number of colors to generate, as input and outputs the generated colors.

Something like this –

//generate colors
function gen_colors(no_of_colors_to_generate) {
  //magic

  //return an array of colors
  return colors;
}

So I decided to start with one color and tweak and shuffle the RGB values to generate random colors.

function color_gen(len) {
  //array in which generated
  //colors are stored
  colors = [];

  function gen_colors(colrs, len) {
    //generate the colors
  }

  //start with rgb(180, 54, 54)
  return gen_colors([180, 54, 54], len);
}
 The full function
function color_gen(len) {
  //array in which generated
  //colors are stored
  colors = [];

  function gen_colors(colrs, len) {
    //loop and create all combinations
    //of the given color
    for (var i = 0; i < 3; i++) {
      for (var j = 0; j < 3; j++) {
        for (var k = 0; k < 3; k++) {
          var color_arr = [colrs[i], colrs[j], colrs[k]];
          //exclude if combination already exists
          //or have the same values ex rgb(180, 180, 180)
          if ((colors.indexOf(rgbize_arr(color_arr)) == -1) && !(colrs[i] == colrs[j] && colrs[i] == colrs[k])) {
            colors.push(rgbize_arr(color_arr));
          }
          //if required colors
          //grater than 25 repeat the 
          //colors generated
          if (colors.length >= 25) {
            colors = colors.concat(colors);
          }
          //if required no. of colors
          //are generated return
          if (colors.length == len) {
            return colors;
          }
          //if generated > required
          //return only required
          else if (colors.length > len) {
            //console.log(colors.slice(0, len));
            return colors.slice(0, len);
          }
          //if combinations are over
          //generate a new first color
          else {
            if (i == 2 && i == j && i == k) {
              var max_colr = Math.max.apply(Math, colrs);
              var min_colr = Math.min.apply(Math, colrs);
              var colr1 = Math.floor((max_colr + min_colr) / 4);
              var colr2 = Math.floor((max_colr + min_colr) / 2);
              var colr3 = Math.floor((max_colr + min_colr) / 3);
              return gen_colors([colr1, colr2, colr3], len);
            }
          }
        }
      }
    }
  }
  //convert array into rgb string
  function rgbize_arr(colr_arr) {
    return 'rgb(' + colr_arr.join() + ')';
  }
  return gen_colors([180, 54, 54], len);
}

Usage

var new_colors = color_gen(25);

Gotta better technique (highly likely), comment below  ???? .

See the color generator in action-

See the Pen Javascript random color generation by hrishikesh mk (@avastava) on CodePen.0

Categories
Programming

Creating a Javascript load more plugin part 2 – Searching2 min read

In the first part Creating a Javascript load more plugin part 1 , we have created a javascript plugin which loads data from an API page. Let’s build upon on it.

Today we are going to add search option to our plugin, children ? .

Objectives ?

  • Add search bar to the page.
  • On input on search bar, load in relevant content from the API.
  • The API should take in a search parameter and provide relevant results.

As of now we are sending two parameters to the API – start and count. We would add one more q for sending the search query.

For learning how add searching option at the server end, please refer this tutorial from Codecourse – Basic PHP & MySQL Searching.

It uses PHP and MYSQL but you get the idea ? .

Demo page – Javascript load more plugin – search added.

We have to add one more line to our previous HTML code to include the search bar.

<input type="search" autocomplete="off" class="finder" />

We can add this anywhere inside our main container. Only condition is that it should have a class of finder, so that our plugin can identify it.

For styling HTML forms and form elements view this tutorial – Styling HTML Forms .

Updating the Plugin

Now let’s upgrade our plugin. First we would find the search bar.

//Search bar
this.finder = this.elem.getElementsByClassName('finder').length ? this.elem.getElementsByClassName('finder')[0] : false;

If you are not able to follow, please go through part one of this series.

Now, inside our lmore.load method we would append the search term to the GET query string.

//create query string with
//start and count variables
var qs = this.source + '?lmore_start=' + this.start + '&lmore_count=' + this.count;

//Send search query if search bar is available
qs += this.finder ? '&q=' + this.finder.value.trim() : '';
this.http.open('GET', qs);
this.http.send();

Let’s add and event listener to the search bar so that, data can be loaded while searching.

We could load data on any event, but I prefer the on-input event because it gives an instant search effect.

I don’t like search bars that have a button which has to be clicked to search. We are in 2016, common guys ( who make me click a button to search ? )  ?.

We could even pass the event, as input for the plugin.

if (this.finder) {
  this.finder.addEventListener('input', function() {
    this.load();
  }.bind(this));
}

You could also use this plugin to give search suggestions like google. Maybe we could use the plugin two times, one for suggestions and one for showing search results.

Comment below if you want to see this plugin give you search suggestions.

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