Live Search Filter with Checkbox PHP - codeigniter

I have issue about the live search with check box. My problem is when i search one the name list the check box is automatically check. only the showed data check.
example i search world "vin"
all have word vin must be checked.
this is my [sample][1]
[1]: http://jsfiddle.net/v921/TxYqv/3/

UPDATED answer:
Here is how your js should look like:
function filter(element) {
var $trs = $('.AvailableGroupLab tr').hide();
var regexp = new RegExp($(element).val(), 'i');
var $numberOfShownRows = 0;
var $rows = $trs.filter(function () {
if($(element).val() != "")
{
$(this).children(':nth-child(1)').html("<input type='checkbox' checked />");
}
else
{
$(this).children(':nth-child(1)').html("<input type='checkbox' />");
}
return regexp.test($(this).children(':nth-child(2)').text());
});
$rows.show();
if($rows.length == 0)
{
$('#message').show();
}
else
{
$('#message').hide();
}
}
$('input:text').on('keyup change', function () {
filter(this);
})
And put this div whereever you want to put your text:
<div id="message" style="display:none"> No record! </div>

Related

How do I add html tags in jquery plugins?

I am doing the live search using the jquery plugins. When I tried to search that doesn't exist, it only shows the table. I would like to put some message "No result found" if it doesnt exist. The question is how can I add message "No result found"
Note: In my codes I add some validation, the user need input minimum of 3 characters
/**
**options to have following keys:
**searchText: this should hold the value of search text
**searchPlaceHolder: this should hold the value of search input box placeholder
**/
(function($)
{
$.fn.tableSearch = function(options)
{
if(!$(this).is('table'))
{
return;
}
var tableObj = $(this),
searchText = (options.searchText)?options.searchText:'Search: ',
searchPlaceHolder = (options.searchPlaceHolder)?options.searchPlaceHolder:'',
divObj = $('<div style="font-size:20px;">'+searchText+'</div><br /><br />'),
inputObj = $('<input style="min-width:25%;max-width:50%;margin-left:1%" type="text" placeholder="'+searchPlaceHolder+'" />'),
caseSensitive = (options.caseSensitive===true)?true:false,
searchFieldVal = '',
pattern = '';
inputObj.off('keyup').on('keyup', function(){
searchFieldVal = $(this).val();
if(searchFieldVal.length == 0)
{
tableObj.find('tbody tr').show();
}
else if(searchFieldVal.length >= 3)
{
pattern = (caseSensitive)?RegExp(searchFieldVal):RegExp(searchFieldVal, 'i');
tableObj.find('tbody tr').hide().each(function()
{
var currentRow = $(this);
currentRow.find('td').each(function()
{
var result = "No result";
$("tbody tr").append(result);
if(pattern.test($(this).html()))
{
currentRow.show();
return false;
}
});
});
}
});
tableObj.before(divObj.append(inputObj));
return tableObj;
}
}(jQuery));
Here into JQ plugin(Posted at your question), the handler for empty result is exist. See piece of code from it.
else if(searchFieldVal.length >= 3)
{
pattern = (caseSensitive)?RegExp(searchFieldVal):RegExp(searchFieldVal, 'i');
tableObj.find('tbody tr').hide().each(function()
{
var currentRow = $(this);
currentRow.find('td').each(function()
{
var result = "No result";
$("tbody tr").append(result);
if(pattern.test($(this).html()))
{
currentRow.show();
return false;
}
});
});
}
Paraphrase you mistaken at your end. Re check it.

Validate that a dropdown is selected if another dropdown is selected

I have two dropdowns on an form. If the user selects a value from the first dropdown, I want to make sure they make a choice from the second dropdown. I'm new to knockout, so I'm not sure how to do this. I don't think I need a fullblown validation library. I just want to stop the action so the popup doesn't go away and some text appears saying "hey you, pick something!"
The row looks like this:
<div class="channelRow" data-bind="foreach: channels">
<div class="channelPrompt">CHANNEL: </div>
<select class="channelSelect" name="channels" data-bind="options: $root.financialVM.channelOptions(), value: name, optionsCaption: '--'"></select>
<div class="portPrompt">NUMBER OF PORTS: </div>
<select class="portSelect" name="ports" data-bind="options: $root.financialVM.portOptions(), value: port, optionsCaption: '--'"></select>
</div>
Update:
Here's the function that I'm working with. Edge is a modal window that appears and is where the select boxes are.
function Edge (siteA, siteB, key, channelpair) {
var edge = this;
edge.siteA = ko.observable(siteA);
edge.siteB = ko.observable(siteB);
edge.distance = ko.observable(0);
edge.key = ko.observable(key);
edge.channels = ko.observableArray([
new ChannelPair()
]);
edge.addChannel = function () {
if(edge.channels().length >= 3) return;
edge.channels.push(new ChannelPair());
};
}
function ChannelPair () {
var channel = this;
channel.name = ko.observable();
channel.port = ko.observable(0);
channel.port.extend({
required: {
message: "You can not have a name without a port",
onlyIf: function () { return (self.name() != null); }
}
});
}
Ok here is a complete solution for you:
// You need this config in order to kick things off
ko.validation.configure({
messagesOnModified: true,
insertMessages: true
});
function Edge (siteA, siteB, key, channelpair) {
var edge = this;
edge.siteA = ko.observable(siteA);
edge.siteB = ko.observable(siteB);
edge.distance = ko.observable(0);
edge.key = ko.observable(key);
edge.channels = ko.observableArray([
new ChannelPair()
]);
edge.addChannel = function () {
if(edge.channels().length >= 3) return;
edge.channels.push(new ChannelPair());
};
}
function ChannelPair () {
var channel = this;
channel.name = ko.observable();
// Extending happens on declaration not after wards
channel.port = ko.observable(0).extend({
required: {
message: "You can not have a name without a port",
// self doesn't mean anything here so replace it with channel like this
onlyIf: function () { return (channel.name() != null); }
}
});
// you need a property called errors to keep your validation group in it
channel.errors = ko.validation.group(channel);
}
Also remember to add knockout validation to your project. Its a plugin and not shipped as part of knockout out of the box.

eval for parsing JSON giving undefined

I am working on Grails framework. I have 2 domain classes Country and City with one-to-many relationship. My idea is when the page is loaded the gsp will have two select boxes, one populating the countries and when any country selected the cities of that country are populated in second select box. here i am using grails ajax (jquery).
import grails.converters.JSON
class CountryController {
def index() { redirect action: 'getCountries' }
def getCountries() {
def countries = Country.list()
render view:'list', model:[countries:countries]
}
def getCities() {
def country = Country.get(params.id)
render country?.city as JSON
}
}
When getCities action is fired i am getting the JSON as below:
[
{
"class":"com.samples.City",
"id":3,
"country":{
"class":"Country",
"id":2
},
"description":"California",
"name":"California"
},
{
"class":"com.samples.City",
"id":4,
"country":{
"class":"Country",
"id":2
},
"description":"Dalls",
"name":"Dalls"
}
]
But from my gsp page when evaluating JSON with eval function, its returning "undefined".
<g:select name="countrySelect" from="${countries}"
optionKey="id" optionValue="name"
noSelection="[null:'Select Country']"
onchange="${
remoteFunction(action: 'getCities',
update: message,
params: '\'id=\' + this.value',
onSuccess:'updateCity(data)')
}"/>
<br/>
City :: <g:select name="city" id="city" from=""></g:select>
Following code in tag
<head>
<g:javascript library="jquery"></g:javascript>
<g:javascript>
function updateCity(data) {
alert('done');
var cities = eval("(" + data.responseText + ")") // evaluate JSON
alert(cities)
var rselect = document.getElementById('city')
// Clear all previous options
var l = rselect.length
while (l > 0) {
l--
rselect.remove(l)
}
//build cities
for(var i=0; i < cities.length; i++) {
var opt = document.createElement('option');
opt.text = cities[i].name
opt.value = cities[i].id
try{
rselect.add(opt,null) //For Non IE
}catch(ex){
rselect.add(opt) //For IE
}
}
}
</g:javascript>
<r:layoutResources />
</head>
Can anyone help me finding out where is the problem?
I got it solved by using JQuery each method on JSON data.
<g:javascript>
function updateCity(data) {
var rselect = document.getElementById('city')
$.each(data, function(index, element) {
//alert(element.name);
var opt = document.createElement('option');
if(element.name !== undefined){
opt.text = element.name
opt.value = element.id
try{
rselect.add(opt,null) //For Non IE
}catch(ex){
rselect.add(opt) //For IE
}
}
});
}
</g:javascript>

knockout validation using breeze utility?

Has anyone written a utility that will convert Breeze metadata (captured from entity framework data attributes) into knockout validation extensions (using knockout.validation)?
I have made an function that reads the metadata from an entity and adds validation rules.
app.domain.indicador = (function () {
"use strict";
var constructor = function () {...}
var initializer = function indicadorInitializer(entity) {
var entityType = entity.entityType;
if (entityType) {
console.log(entityType);
for (var i = 0; i < entityType.dataProperties.length; i++) {
var property = entityType.dataProperties[i];
console.log(property);
var propertyName = property.name;
var propertyObject = entity[propertyName];
if (!property.isNullable) {
propertyObject.extend({ required: true });
}
if (property.maxLength) {
propertyObject.extend({ maxLength: property.maxLength });
}
}
for (var i = 0; i < entityType.foreignKeyProperties.length; i++) {
var property = entityType.foreignKeyProperties[i];
console.log(property);
var propertyName = property.name;
var propertyObject = entity[propertyName];
if (!property.isNullable) {
propertyObject.extend({ required: true });
}
if (property.maxLength) {
propertyObject.extend({ maxLength: property.maxLength });
}
//Bussines rule
propertyObject.extend({ notEqual: 0 });
}
}
};
return {
constructor: constructor,
initializer: initializer
};
})();
I use the function as initializer:
store.registerEntityTypeCtor("Indicador", domain.indicador.constructor, domain.indicador.initializer);
It's just a start but for the time is useful for me.
Update:
I changed the way I add validation. I share it here in case it is useful to someone:
Helper object:
app.validatorHelper = (function (breeze) {
var foreignKeyInvalidValue = 0;
function addDataTypeRules(dataType, property) {
switch (dataType) {
case breeze.DataType.DateTime:
//TODO: implement my function to validate dates. This validator is too permissive
property.extend({ date: true });
break;
case breeze.DataType.Int64:
case breeze.DataType.Int32:
case breeze.DataType.Int16:
//it's needed to accept negative numbers because of the autogenerated keys
property.extend({ signedDigit: true });
break;
case breeze.DataType.Decimal:
case breeze.DataType.Double:
case breeze.DataType.Single:
property.extend({ number: true });
break;
}
};
function addValidationRules(entity) {
var entityType = entity.entityType;
if (entityType) {
for (var i = 0; i < entityType.dataProperties.length; i++) {
var property = entityType.dataProperties[i];
//console.log(property);
var propertyName = property.name;
var propertyObject = entity[propertyName];
addDataTypeRules(property.dataType, propertyObject);
if (!property.isNullable) {
propertyObject.extend({ required: true });
}
if (property.maxLength) {
propertyObject.extend({ maxLength: property.maxLength });
}
}
for (var i = 0; i < entityType.foreignKeyProperties.length; i++) {
var property = entityType.foreignKeyProperties[i];
//console.log(property);
var propertyName = property.name;
var propertyObject = entity[propertyName];
addDataTypeRules(property.dataType, propertyObject);
if (!property.isNullable) {
propertyObject.extend({ required: true });
//Bussiness Rule: 0 is not allowed for required foreign keys
propertyObject.extend({ notEqual: foreignKeyInvalidValue });
}
if (property.maxLength) {
propertyObject.extend({ maxLength: property.maxLength });
}
}
}
};
return {
addValidationRules: addValidationRules
};
})(breeze);
The custom validator:
(function (ko) {
ko.validation.rules['signedDigit'] = {
validator: function (value, validate) {
if (!validate) return true;
return ko.validation.utils.isEmptyVal(value) || (validate && /^-?\d+$/.test(value));
},
message: 'Please enter a digit'
};
ko.validation.registerExtenders();
})(ko);
Using the helper at the initializer:
app.domain.valorIndicador = (function (vHelper) {
"use strict";
var constructor = function () {
};
var initializer = function indicadorInitializer(entity) {
vHelper.addValidationRules(entity);
};
return {
constructor: constructor,
initializer: initializer
};
})(app.validatorHelper);
And setting the initializer:
store.registerEntityTypeCtor("ValorIndicador", domain.valorIndicador.constructor, domain.valorIndicador.initializer);
A simple way to bind validation errors from breezejs using knockout.
We can subscribe to validationErrorsChanged event from the entityAspect:
function subscribeValidation() {
return self.entity().entityAspect.validationErrorsChanged.subscribe(function (validationChangeArgs) {
validationChangeArgs.added.forEach(function (item) { addError(item); });
validationChangeArgs.removed.forEach(function (item) { self.validationErrors.remove(item); });
});
}
this.hasError = function (propertyName) {
var array = self.validationErrors();
var match = array.filter(function (item) {
return item.propertyName == propertyName;
});
if (match.length > 0) {
return true;
} else return false;
};
function addError(item) {
self.validationErrors.remove(function (i) {
return i.propertyName == item.propertyName;
});
self.validationErrors.push(item);
}
Finally we can bind to the messages on the UI (I'm using Twitter boostrap css classes)
<div class="control-group" data-bind="css: { 'error': hasError('Nome') }">
<label class="control-label">Nome</label>
<div class="controls">
<input type="text" class="input-xxlarge" data-bind="value: model().Nome">
<span class="help-inline" data-bind="text: getErrorMessage('Nome')"></span>
</div>
</div>
See the full gist here
I've searched this before as I started using breeze with knockout and then I had the exact same question about how to validate stuff, and how to show validation inline.
Considering that breeze already has validation built in, I decided to write a custom Knockout Binding to show the validation result every time the observable value changes and it was quite easy afterall:
Here's the custom binding:
ko.bindingHandlers.breezeValidate = {
init: function (element, valueAccessor, allBindingsAccessor, context) {
var isOk = context.entityAspect.validateProperty(valueAccessor());
var errors = context.entityAspect.getValidationErrors(valueAccessor());
var message = "";
if (errors.length > 0)
message = errors[0].errorMessage;
$(element).html(message);
},
//update the control when the view model changes
update: function (element, valueAccessor, allBindingsAccessor, context) {
debugger;
this.init(element, valueAccessor, allBindingsAccessor, context)
}
};
And the usage is like this:
<span data-bind="text: Name"></span>
<span data-bind="breezeValidate: 'Name'"></span>
This works because of this line:
var isOk = context.entityAspect.validateProperty(valueAccessor());
When breeze is requested to validate the property it ends up calling the observable and it gets registered by knockout, so every time it is changed, this binding will be invoked again and the error message will be updated accordingly.
I'm just showing the first validation message, but of course you can iterate thru all of them and even add a different styling to the element.
Hope this helps!!
Not sure why people would want to use ko.validation - it just replicates the processing breeze's client side is doing anyway. And given the breeze developers hints that validation will get even more power soon, why bother.
So I started with Thiago Oliveira's great work. But I wanted to have the bare minimum of markup. By assuming the use of bootstrap classes & defaulting the validation property name from the previous element I could simplify most markup additions to:
<span class="help-inline" data-bind="breezeValidation: null"></span>
Win!
My ko.bindingHandler:
//Highlight field in red & show first validation message
//
//Outputs first validation message for 'propertyName' or if null: previous controls value binding
//Needs ancestor with 'control-group' class to set class 'error' for Bootstrap error display
//
//Example:
//<td class="control-group">
// <input class="input-block-level text-right" data-bind="value: id" />
// <span class="help-inline" data-bind="breezeValidation: null"></span>
//</td>
//
//Does not and cannot validate keys that already exist in cache. knockout write calls breeze which throws uncaught error
ko.bindingHandlers.breezeValidation = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
var $msgElement = $(element);
var entity = viewModel;
var propName = valueAccessor();
if (propName === null) {
// $element.prev().data("bind") = "value: itemType"
var prevBinds = $msgElement.prev().data("bind");
if (!prevBinds) {
$msgElement.text("Could not find prev elements binding value.");
return;
}
var bindPhrases = prevBinds.split(/,/);
for (var i = 0, j = bindPhrases.length; i < j; i++) {
var bindPhrase = bindPhrases[i];
if (utility.stringStartsWith(bindPhrase, 'value: ')) {
propName = bindPhrase.substr(7);
break;
}
}
}
if (!propName) {
$msgElement.text("Could not find this or prev elements binding value.");
return;
}
//var $groupElement = $msgElement.parent();
var $groupElement = $msgElement.closest(".control-group");
if (!$groupElement.hasClass("control-group")) {
$msgElement.text("Could not find parent with 'control-group' class.");
return;
}
onValidationChange(); //fire immediately (especially for added)
//... and anytime validationErrors are changed fire onValidationChnange
entity.entityAspect.validationErrorsChanged.subscribe(onValidationChange);
element.onchange = function () {
//Should never have updates pushed from validation msgElement
$msgElement.text("readonly error");
};
function onValidationChange() {
var errors = entity.entityAspect.getValidationErrors(propName);
var message = "";
if (errors.length > 0) {
message = errors[0].errorMessage;
}
if (message) {
$groupElement.addClass('error');
}
else {
$groupElement.removeClass('error');
}
$msgElement.text(message);
}
}
//Not interested in changes to valueAccessor - it is only the fieldName.
//update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
};
Example view simple implicit property usage:
<div class="control-group">
<label class="control-label" for="editStatusNote">Status note:</label>
<div class="controls">
<input id="editStatusNote" type="text" data-bind="value: statusNote" />
<span class="help-inline" data-bind="breezeValidation: null"></span>
</div>
</div>
Example view explicit property usage:
<div class="control-group">
<label class="control-label" for="editAmount">Amount:</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on">$</span>
<input id="editAmount" class="input-small" type="text" data-bind="value: amount" />
</div>
<span class="help-inline" data-bind="breezeValidation: 'amount'"></span>
</div>
</div>
I updated breezeValidation to Bootstrap 3 and improved with multipath property support.
ko.bindingHandlers.breezeValidation = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
var $msgElement = $(element);
var entity = viewModel;
var propName = valueAccessor();
if (propName === null) {
// $element.prev().data("bind") = "value: itemType"
var prevBinds = $msgElement.prev().data("bind");
if (!prevBinds) {
$msgElement.text("Could not find prev elements binding value.");
return;
}
var bindPhrases = prevBinds.split(/,/);
for (var i = 0, j = bindPhrases.length; i < j; i++) {
var bindPhrase = bindPhrases[i];
if (bindPhrase.substr(0, 7) == 'value: ') {
propName = bindPhrase.substr(7);
entity = ko.utils.unwrapObservable(entity);
var propPath = propName.replace(/[()]/g, "").split('.'), i = 0;
var tempProp = entity[propPath[i]], links = propPath.length;
i++;
while (ko.utils.unwrapObservable(tempProp) && i < links) {
entity = ko.utils.unwrapObservable(tempProp);
tempProp = entity[propName = propPath[i]];
i++;
}
break;
}
}
}
if (!propName) {
$msgElement.text("Could not find this or prev elements binding value.");
return;
}
//var $groupElement = $msgElement.parent();
var $groupElement = $msgElement.closest(".form-group");
if (!$groupElement.hasClass("form-group")) {
$msgElement.text("Could not find parent with 'form-group' class.");
return;
}
onValidationChange(); //fire immediately (especially for added)
//... and anytime validationErrors are changed fire onValidationChnange
entity.entityAspect.validationErrorsChanged.subscribe(onValidationChange);
element.onchange = function () {
//Should never have updates pushed from validation msgElement
$msgElement.text("readonly error");
};
function onValidationChange() {
var errors = entity.entityAspect.getValidationErrors(propName);
var message = "";
if (errors.length > 0) {
message = errors[0].errorMessage;
}
if (message) {
$groupElement.addClass('has-error');
}
else {
$groupElement.removeClass('has-error');
}
$msgElement.text(message);
}
}
//Not interested in changes to valueAccessor - it is only the fieldName.
//update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
};
Knockout validator can use breeze validation as a whole:
function addKoValidationRules(entity) {
if (entity.koValidationRulesAdded) {
return;
}
entity.entityType.dataProperties.forEach(function (property) {
entity[property.name].extend({
validation: {
validator: function () {
// manual validation ensures subscription to observables which current field depends on
// entity is added to context for retrieving other properties in custom validators
entity.entityAspect.validateProperty(property.name, { entity: entity });
var errors = entity.entityAspect.getValidationErrors(property.name);
if (!errors.length) {
return true;
}
this.message = errors[0].errorMessage;
return false;
},
message: ''
}
});
});
entity.koValidationRulesAdded = true;
}

Inline editing with AJAX - how do I create multiple editable areas on the same page?

I found a tutorial on how to create editable regions on a page using AJAX.
This is great, except it was written for a single element with a unique ID. I'd like to be able to click on multiple elements on the same page and have them also be editable (e.g., I'd like to alter the script below so it works not with a single element, but with multiple elements of a particular class).
Here is my HTML:
<h2>Edit This</h2>
<p class="edit">This is some editable content</p>
<p class="edit">This is some more editable content</p>
<p class="edit">I could do this all day</p>
Here is the JS file I'm working with (I updated the script per Rex's answer below): This script is, unfortunately, not working - can anyone point me in the right direction?
Event.observe(window, 'load', init, false);
function init() {
makeEditable('edit');
}
function makeEditable(className) {
var editElements = document.getElementsByClassName(className);
for(var i=0;i<editElements.length;i++) {
Event.observe(editElements[i], 'click', function(){edit($(className))}, false);
Event.observe(editElements[i], 'mouseover', function(){showAsEditable($(className))}, false);
Event.observe(editElements[i], 'mouseout', function(){showAsEditable($(className), true)}, false);
}
}
function showAsEditable(obj, clear) {
if (!clear) {
Element.addClassName(obj, 'editable');
} else {
Element.removeClassName(obj, 'editable');
}
}
function edit(obj) {
Element.hide(obj);
var textarea ='<div id="' + obj.id + '_editor"><textarea cols="60" rows="4" name="' + obj.id + '" id="' + obj.id + '_edit">' + obj.innerHTML + '</textarea>';
var button = '<input type="button" value="SAVE" id="' + obj.id + '_save"/> OR <input type="button" value="CANCEL" id="' + obj.id + '_cancel"/></div>';
new Insertion.After(obj, textarea+button);
Event.observe(obj.id+'_save', 'click', function(){saveChanges(obj)}, false);
Event.observe(obj.id+'_cancel', 'click', function(){cleanUp(obj)}, false);
}
function cleanUp(obj, keepEditable) {
Element.remove(obj.id+'_editor');
Element.show(obj);
if (!keepEditable) showAsEditable(obj, true);
}
function saveChanges(obj) {
var new_content = escape($F(obj.id+'_edit'));
obj.preUpdate = obj.innerHTML // stow contents prior to saving in case of an error
obj.innerHTML = "Saving…";
cleanUp(obj, true);
var success = function(t){editComplete(t, obj);}
var failure = function(t){editFailed(t, obj);}
var url = 'http://portal.3roadsmedia.com/scripts/edit.php';
var pars = 'id=' + obj.id + '&content=' + new_content + '&pre=' + obj.preUpdate;
var myAjax = new Ajax.Request(url, {method:'post',
postBody:pars, onSuccess:success, onFailure:failure});
}
function editComplete(t, obj) {
obj.innerHTML = t.responseText;
showAsEditable(obj, true);
}
function editFailed(t, obj) {
obj.innerHTML = 'Sorry, the update failed.';
cleanUp(obj);
}
The Event.observe method currently attaches to a single element with the ID specified. You should change this to iterate over a collection of elements located by classname and attach to each of them. According to the Prototype documentation, you can provide an element object as the first parameter, instead of an ID.
Currently, id is a string:
function makeEditable(id) {
Event.observe(id, 'click', function(){edit($(id))}, false);
//...
Which means Event.observe is attaching to the click event of the element with the ID provided. You want to attach to all elements with a class. Try:
function makeEditable(className) {
var editElements = document.getElementsByClassName(className);
for(var i=0;i<editElements.length;i++) {
Event.observe(editElements[i], 'click', function()
//...
}
//...

Resources