List.JS - Filter with comma separated values - list.js

I'm trying to create a dropdown to filter based on dates, but I would like to be able to comma separate the dates instead of initilizing each field as a separate filter, which would be slow when you account for hundreds of dates, and each list item having 30+ dates each.
I thought maybe list.js supports comma separated fields, but I can't find any obvious solution online.
Here is a simple codepen with the code working with a single field:
https://codepen.io/mauricekindermann/pen/QWyqzQL
This: <span class="stat filter_dates">1999,2099,2199</span>
Instead of this: <span class="stat filter_dates">1999</span>
Is this possible? Or do I need to initiate each date as a separate filter?

I didn't get any answers and couldn't find an obvious soultion to this. So the final result uses this method (JS script inside a PHP file)
<script>
var options = {
valueNames: [
'id',
<?
while($item= mysqli_fetch_array($query))
{
?>
'filter_<?=$item['id']?>',
<?
}
?>
]
};
$(document).ready(function()
{
if($('#filter').length > 0)
{
$('#filter').change(function ()
{
var selection = this.value;
<?
$i=0;
mysqli_data_seek($query, 0);
while($item= mysqli_fetch_array($query))
{
if($i==0){
$type='if';
} else {
$type='else if';
}
?>
<?=$type?>(selection == '<?=$item['id']?>')
{
userList.filter(function (item) {
return (item.values().<?='filter_'.$item['id']?> == selection);
});
}
<?
$i++;
}
if($i > 0){
?>
else {
userList.filter();
}
<?
}
?>
});
};
});
</script>

Related

How do I query a Meteor.publication collection by a component prop correctly?

Given the following React component, I am passing this component this.ticket.props AND I am subscribing to a collection called userReservations. The ticket properties are rendering correctly i.e. each ticket is rendering only it's specific properties.
However inside the .renderReservationInfo() method. After I make the Meteor.subscription call with the ticket._id value as a selector in the createContainer class, which corresponds to the "ticketId" value in the UserReservation collection, the Meteor publication responds with the correct collection info but renders it to every ticket.
If I'm querying by ticket._id, why is the collection applied to both tickets? How can I render just the reservation info to the corresponding ticket._id?
Are there react lifecycle components that can help me manage this?
class ComponentName extends React.Component {
renderReservationInfo() {
let {
ticket,
UserReservation
} = this.props;
return UserReservation.map((reservation) => {
return (
<div key = {reservation._id} >
< h4 > {reservation.property1} < /h4>
< h4 > {reservation.property2} < /h4>
< h4 > {reservation.property3} < /h4>
<Component2 prop = {reservation} />
</div >
)
});
}
render() {
return (
<div >
< div className = "make-it-pretty" >
< h4 > Ticket Price: $ { this.props.ticket.property1 } </h4>
< h4 > Ticket Price: $ { this.props.ticket.property2 } </h4>
< h4 > Ticket Price: $ { this.props.ticket.property3 } </h4>
{ this.renderReservationInfo() }
</div>
</div >
)
}
}
export default createContainer(({ ticket }) => {
Meteor.subscribe('userReservations', ticket._id);
return {
UserReservation: UserReservations.find({}).fetch()
};
}, ComponentName);
And my Publication info
//Server
Meteor.publish('userReservations', function(ticket_Id) {
if (!ticket_Id) {
console.log('No ticketId sent');
} else {
console.log('sending UserReservations', ticket_Id);
return UserReservations.find({ ticketId:ticket_Id });
}
});
Okay so this turned out to be a simple enough solution. I had previously thought I needed to keep my subscribe call empty in the client side for security purposes, and maybe that's an accurate statement, but inserting the the specific ticketId I was able to start returning what I needed to in the correct way.
Also by making stricter query parameters in my publication.find() I was able to limit what was sent back. I think this is probably an example of a simple problem that I snowballed into a bigger one.

recall form value not working for textareas

Im trying to modify this script
http://www.dynamicdrive.com/dynamicindex16/formremember2.htm
to work for textareas, and not just input text boxes. Heres what im guessing are the relevant parts of the script, i just cant figure it out myself
rememberForm.prototype.savevalues=function(){ //get form values and store in cookie
for (var i=0; i<this.fields.length; i++){
if (this.fields[i].type=="text")
this.cookiestr+=this.fields[i].fname+":"+escape(this.fields[i].value)+"#"
}
if (typeof this.togglebox!="undefined"){ //if "remember values checkbox" is defined
this.persistdays=(this.togglebox.checked)? this.persistdays : -1 //decide whether to save form values
this.cookiestr=(this.togglebox.checked)? this.cookiestr+"toggleboxid:on;" : this.cookiestr
}
else //if checkbox isn't defined, just remove final "#" from cookie string
this.cookiestr=this.cookiestr.substr(0, this.cookiestr.length-1)+";"
setCookie(this.cookiename, this.cookiestr, this.persistdays)
}
rememberForm.prototype.recallvalues=function(){ //populate form with saved values
var cookievalue=getCookie(this.cookiename)
if (cookievalue!=""){ //parse cookie, where cookie looks like: field1:value1#field2:value2...
var cookievaluepair=cookievalue.split("#")
for (var i=0; i<cookievaluepair.length; i++){
if (cookievaluepair[i].split(":")[0]!="toggleboxid" && this.getfield(cookievaluepair[i].split(":")[0]).type=="text")
this.getfield(cookievaluepair[i].split(":") [0]).value=unescape(cookievaluepair[i].split(":")[1])
else //else if name in name/value pair is "toggleboxid"
this.togglebox.checked=true
}
}
The method persistfields(id, ...) sets the fields you want to persist in the cookie. The fields are looked up by id so I guess adding a textarea with an id attribute would suffice.
For example:
<form id="myFormId">
<input type="text" id="someInputId" />
<textarea id="textareaId"></textarea>
</form>
<script>
var f = new rememberForm('myFormId');
f.persistfields('someInputId', 'textareaId');
</script>
This will add the input and textarea to the rememberForm instance fields property.
UPDATE
The problem lies in this method of rememberForm. I formatted the code for readability since the original source has horrible formatting.
rememberForm.prototype.savevalues = function() {
for (var i = 0; i < this.fields.length; i++) {
// PROBLEM: only allows type="text"
if (this.fields[i].type == "text") {
this.cookiestr += this.fields[i].fname + " : " + escape(this.fields[i].value) + "#"
}
if (typeof this.togglebox != "undefined") {
this.persistdays = (this.togglebox.checked) ? this.persistdays : -1;
this.cookiestr = (this.togglebox.checked) ? this.cookiestr + "toggleboxid:on;" : this.cookiestr
} else {
this.cookiestr = this.cookiestr.substr(0, this.cookiestr.length - 1) + ";"
setCookie(this.cookiename, this.cookiestr, this.persistdays)
}
}
}
As mentioned in my comment it will test the type of the input element to be 'text'. If you'd like to add textareas in the cookie you could change that line to:
if (this.fields[i].type == "text" || this.fields[i].type == 'textarea') {
That should work.

Validate phone number in form

I am trying to get my code to work for a form. I want it to validate a phone number. It want to continue to tell me the phone number is not correct even when it is.
Here's what I have. I took out the rest of the code that pertain to this part to simplify it. I am not sure if I have the code right but I am looking to have someone only be able to type number. Enter a 10 digit string of number and have it change to the following format (XXX) XXX-XXXX if this is possible.
<?php
include_once "contact-config.php";
$error_message = '';
if (!isset($_POST['submit'])) {
showForm();
} else { //form submitted
$error = 0;
if(!empty($_POST['phone'])) {
$phone[2] = clean_var($_POST['phone']);
if (!validPhone($phone[2])) {
$error = 1;
$phone[3] = 'color:#FF0000;';
$phone[4] = '<strong><span style="color:#FF0000;">Invalid Phone Number</span></strong>';
}
}
else {
$error = 1;
$phone[3] = 'color:#FF0000;';
}
<td class="quote_text" style="width:{$left_col_width}; text-align:right; vertical-align:top; padding:{$cell_padding}; {$phone[3]}"><span class='required'><b>* </b></span>{$phone[0]}</td>
<td style="text-align:left; vertical-align:top; padding:{$cell_padding};"><input type="text" name="{$phone[1]}" value="{$phone[2]}" size="20" maxlength="11" id="{$phone[1]}" /> {$phone[4]}</td>
/* Phone Number Validation Function. */
function validPhone($phone)
{
$isValid = true;
if(array_key_exists('phone', $_POST))
{
if(!preg_match('/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $_POST['phone']))
{
$isValid = false;
}
}
return $isValid;
}
?>
I have a few comments about your original code although I have not gone into the debugging in depth.
There's a regex at http://php.net/manual/en/function.preg-match.php that is more complicated you might try. It's about halfway down the page. I tried your regex out at both http://regexpal.com/ and http://www.solmetra.com/scripts/regex/index.php ; it did not work at either place on phone numbers I used. The regex I pulled from the PHP reference page, as shown below, works.
/^(?:1(?:[. -])?)?(?:((?=\d{3})))?([2-9]\d{2})(?:(?<=(\d{3})))? ?(?:(?<=\d{3})[.-])?([2-9]\d{2})[. -]?(\d{4})(?: (?i:ext).? ?(\d{1,5}))?$/
You're calling the function with a parameter then not using the parameter in the function body, which strikes me as strange.
This is probably a duplicate topic of PHP: Validation of US Phone numbers which is pretty comprehensive.

Zend_Form with Ajax/json

I'm a bit lost using Zend_Form with Ajax. I have a form in a class extending Zend_Form called from my controller, that way :
GoodAddGroup.php
class Default_Form_GoodAddGroup extends Zend_Form {
(...)
public function init()
{
$this->setMethod('post');
$this->setAction("process-add-group");
$this->setName("addgroupgood");
// Load Elements class
require "Form/Elements.php";
$magElements = new Elements();
// Category
$categoryElement = $magElements->getCategorySelectField();
$categoryElement->setDecorators($this->elementDecorators);
// Barcode
$barcodeElement = $magElements->getGoodBarcodeTextField();
$barcodeElement->setDecorators($this->elementDecorators);
(...)
// Add elements to the form
$this->addElements(array(
$categoryElement,
//$codeElement,
$barcodeElement,
$serialElement,
$warehouseElement,
$submitButtonElement
));
$this->setDecorators($this->formDecorators);
}
}
In GoodsController.php
private function getAddGroupForm()
{
return new Default_Form_GoodAddGroup();
}
public function addGroupAction()
{
// Initialize the form for the view.
$this->view->form = $this->getAddGroupForm();
}
public function processAddGroupAction()
{
$form = $this->getAddGroupForm();
(...)
if ($_POST)
{
if ($form->isValid($_POST))
{
// Do things
} else {
$this->view->form = $form;
}
}
}
Basically, the form has a category select field, when selecting a category, a second "code" selector is added filled with the items related to this category. When the page with the form is displayed (http://myapp/goods/add-group), everything works fine, the ajax call does its job, the second select field is added and well fed, but as you can see, the form processing is done with the processAddGroupAction(), this method get the instance of the form to get its values and to re-display it in case of problem. But that way, my "new" select field doesn't exist anymore, so i can never validate the form.
It's my first attempt using ajax/json with Zend, i think i need help at this poind.
Thank you.
EDIT : added the view code as requested
<script>
$(function(){
$("#cats").change(function(){
getSelectBox(this);
});
$("#code").parent().parent().css('display', 'none');
getSelectBox($("#cats"));
});
function getSelectBox(element)
{
if($(element).val() != '')
{
$("#code").parent().parent().css('display', 'block');
if ($('#code').length <= 0) {
$("#cats").after('<select name="code" id="code" style="margin-left:10px"></select>');
}
$.getJSON("/goods/json-get-codes-from-category", {id: $(element).val(), ajax: "true"}, function(j){
console.log(j);
var options = "";
jQuery.each(j, function(i, val) {
options += '<option value="' + i + '">' + i + val + '</option>';
});
$("#code").html(options);
});
}
}
</script>
<?php echo $this->form; ?>
You can add the select element 'code' in the form, but don't display it in the view (it will be created from the js). So when the form is posted the 'code' will also be validated since it is in the $_POST.
After post you have to display the select box without $("#cats").change({..}). You can accomplish it by spiting the js code into functions
<script>
$(function(){
$("#cats").change(function(){
getSelectBox(this);
});
getSelectBox($("#cats"));
});
function getSelectBox(element)
{
if($(element).val() != '')
{
if ($('#code').length <= 0) {
$("#cats").after('<select name="code" id="code" style="margin-left:10px"></select>');
}
$.getJSON("/goods/json-get-codes-from-category", {id: $(element).val(), ajax: "true"}, function(j){
console.log(j);
var options = "";
jQuery.each(j, function(i, val) {
options += '<option value="' + i + '">' + i + val + '</option>';
});
$("#code").html(options);
});
}
}
</script>
Hope this helps
Ok, i found the solution! I post it in case it can be useful for other people.
I knew what was the problem, but unable to know how to achieve it.
At form processing time, the new select element does not exist for the action as it has been added in the view with javascript. To fix this, we need to inform the action about the new field, to do so, we first need to override the method “isValid” of Zend_Form in the form class :
public function isValid($values)
{
$values = $this->_modifyElements($values);
return parent::isValid($values);
}
Then create a method "_modifyElements" that will modify the form by adding the new element :
protected function _modifyElements($values)
{
// Search for codes
$dbu = new DbUtils();
$codes = $dbu->getCodesFromCategory($values['cats']);
// Remove the current code element
$this->removeElement('code');
// Create a new element
$codeElement = new Zend_Form_Element_Select('code', array());
$codeElement->setLabel(_('Code :'));
$codeElement->setRequired(true);
$codeElement->addMultiOptions($codes);
$codeElement->setValue($values['code']);
$codeElement->setDecorators($this->elementDecorators);
$this->addElement($codeElement);
return $values;
}
We have to override the method "populate" too :
public function populate(array $values)
{
$values = $this->_modifyElements($values);
return parent::populate($values);
}
And voilà. It works for me ;>
All the credits about this go to Mohamed : http://jamandcheese-on-phptoast.com/2009/12/13/on-fly-elements-in-zend_form/

How to create nested <ul> <li> tags with HtmlTags (FubuMVC)

I have no previous experience with FubuMVC HtmlTags library, and I simply got stuck when trying to accomplish a simple nested structure like this:
<ul>
<li>text</li>
<li>text
<ul>
<li>subtext</li>
<li>subtext</li>
</ul>
</li>
<li>text</li>
</ul>
Here's how I have it when building the string:
public static HtmlString ChildNodesRecursive(DocumentNode documentNode)
{
var tag="";
if (documentNode.Children.Count > 0)
{
tag = "<ul>";
foreach (var c in documentNode.Children)
{
tag += "<li>" + c.Name;
tag += ChildNodesRecursive(c);
tag += "</li>";
}
tag += "</ul>";
}
return new HtmlString(tag);
}
Works fine, but I like to use HtmlTags library (outside of FubuMvc, with the HtmlTags separate Nuget).
Edit : I got inspiration from both answers and came up with what I needed. So here's the code I ended up using.
public static HtmlTags.HtmlTag ChildNodesRecursiveHtmlTag(DocumentNode documentNode)
{
var ul = new HtmlTags.HtmlTag("ul");
foreach (var c in documentNode.Children)
{
var li = new HtmlTags.HtmlTag("li");
li.Add("a").Attr("href",c.ContextFullPath).Text(c.Name);
if (c.Children.Count > 0)
{
li.Children.Add(ChildNodesRecursiveHtmlTag(c));
}
ul.Children.Add(li);
}
return ul;
}
I can give you an example which may make things clearer to you:
var ul = new HtmlTag("span").AddClass("form_input");
ul.Modify(t =>
{
foreach (var value in choice)
{
t.Add("input")
.Attr("type", "radio")
.Attr("name", request.Accessor.Name)
.Attr("value", value)
.Add("span")
.AddClass("fixed-width")
.Text(value);
}
});
Gives you something like
<span class="form-input">
<input type="radio" name="bla" value="foo" />
<span class="fixed-width">foo</span>
...etc...
</span>
You can carry on nesting tags with modify and filling in the lambda. I think you will find that what you want to do is possible with the bits of syntax shown.
This code:
var root = new HtmlTags.HtmlTag("ul");
root.Add("li").Text("item1");
var child = root.Add("ul");
child.Add("li").Text("item2");
return root.ToPrettyString();
produces the following output:
<ul>
<li>item1</li><ul>
<li>item2</li>
</ul>
</ul>