<!DOCTYPE html>
<html>

  <head>
    <link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
    <script data-require="jquery@2.1.3" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <script data-require="knockout@3.3.0" data-semver="3.3.0" src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
    <script data-require="knockout-validation@2.0.3" data-semver="2.0.3" src="https://cdn.jsdelivr.net/knockout.validation/2.0.3/knockout.validation.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
    <script src="hlvalidationComponent.js"></script>
    
  </head>

  <body>
    <h4> KO Validations</h4> <hr/>
  
    <hl-validation  params="serverError: serverError"></hl-validation>
    
    
    
    
    <p class='validationMessage' data-bind="validationMessage: remoteValidationError"></p>
    
    <table class="table" >
      <tbody>
        <tr>
          <td>Name</td>
          <td>
            <input type="text" data-bind="value:firstName" />
             <p class='validationMessage' data-bind="validationMessage: firstName"></p>
          </td>
        </tr>
        <tr>
          <td>Description</td>
          <td>
            <input type="text" data-bind="value:description" />
          </td>
        </tr>
        <tr>
          <td>Remote User Name:</td>
          <td>
            <input type="text" data-bind="value:userName" />
          </td>
        </tr>
        <tr>
          <td>Digit:</td>
          <td>
            <input type="text" data-bind="value:digit" />
          </td>
        </tr>
        <tr>
          <td></td>
          <td>
            <input type="button" value="Save" data-bind="click: ok" />
                        <input type="button" value="Search" data-bind="click: search" />
          </td>
        </tr>
      </tbody>
    </table>
    
   
    <hr/>
    
      some examples for extending:    http://jsfiddle.net/KHFn8/5424/
    
  </body>

</html>

var Customer = function(){

 var self = this;
 self.movieData = ko.observable();
 self.digit = ko.observable(12).extend({between:[10,20]});
 self. remoteValidation = ko.observable(false);
 self.remoteValidationError= ko.observable();
 self.remoteValidationMessage = ko.observable();
 self.firstName = ko.observable().extend({required: true});
 self.description = ko.observable().extend({
   required:{message:"please enter description"}});
 self.serverError = ko.observable();
 self.userName = ko.observable("").extend({
  required: {
            message: self.remoteValidationMessage()
        }
   
 });
 
 // conditional errors display
 self.remoteValidationError = ko.observable("").extend({
  required: {
            onlyIf: function() {return self.remoteValidation();},
            params:self.remoteValidationMessage,
            message: function(){return self.remoteValidationMessage();}
            }
 });
 

  

 
 
 var isValid = function(){
   self.errors.showAllMessages();
   return  self.errors().length===0;
 }
 
 self.ok = function(){
   if(isValid()){
    var url = "https://www.omdbapi.com/?t=frozen&y=&plot=short&r=json";   
    
    $.get( url, function(result){
      self.serverError("This is server validation error after ajax call for save");
      //self.movieData(JSON.stringify(result));
      //self.remoteValidationMessage("User name is alredy exists in the system");
      //self.remoteValidation(true);
      //isValid(); 
    });
   }
 };
 
 self.search = function(){
  var url = "https://www.omdbapi.com/?t=frozen&y=&plot=short&r=json";
  $.get( url, function(result){
     self.movieData(JSON.stringify(result));
     self.serverError("This is server validation error after ajax call for search");
  });
};

// init validations
 self.errors =  ko.validation.group(self);
 
};





$(function(){
  ko.applyBindings(new Customer());


});
  

/* Styles go here */

.validationMessage {
    padding-left:10px;
    color: #f00;
}
.customMessage {
  padding-left:10px;
    color: #f00;
}
ko.validation.rules.pattern.message = 'Invalid.';
var koValidationSettings = {
   insertMessages: true,// show message next or input or not 
    decorateElement: true,
    errorMessageClass: 'validationMessage',
    errorElementClass: 'validationMessage',
    errorClass: 'validationMessage',
    errorsAsTitle: true,
    parseInputAttributes: false,
    messagesOnModified: true,
    decorateElementOnModified: true,
    decorateInputElement: true
};

ko.validation.init(koValidationSettings, true);

ko.validation.rules.between = {
    validator: function(value, params) {
        var min = params[0];
        var max = params[1];
        
        value = parseInt(value, 10);
        
        if (!isNaN(value)) {
            return value >= min && value <= max;
        }
        return false;   
    },
    message: 'Value must be between {0} and {1}'
};

ko.validation.registerExtenders();

ko.components.register("hl-validation", {
    viewModel: function(params) {
      
      var self = this;
      self.hasRemoteError = ko.observable(false);
      self.remoteError = ko.observable("");
      
      
      
       self.firstName = ko.observable().extend({required: {
            onlyIf: function() {return self.hasRemoteError();},
            params:self.remoteError,
            message: function(){return self.remoteError();}
            }
      });
      
      params.serverError.subscribe(function(){
        if(params.serverError().length>0){
          
          self.hasRemoteError(true);
          self.remoteError(params.serverError());
          self.errors.showAllMessages();
        }
      })
      
      self.errors =  ko.validation.group(self);
      
      
    },
    template: "<h4>validation comp.: </h4> <span class='validationMessage' data-bind='validationMessage:firstName'> </span>"});