Opencart 3.0.2.3 - Autocomplete() function added to customer_group.php - jquery-ui-autocomplete

Attempting to add some feauture to Customer Groups I got stuck when needing for the autocomplete function which will get products so I can add them to specific customer groups when needed that will be shown on their My Account page. I cannot find what Im missing in order to get the autocomplete to work since it not showing the list <li> like the autocomplete in Categories (Product --> Links). I can see the <li> list with Element Inspector of Product->Links Category but not on my custom Customer Groups Form.
To give more light, this is what I have donde so far:
admin/controller/customer/customer_group.php
public function autocomplete() {
$json = array();
if (isset($this->request->get['filter_name'])) {
$this->load->model('customer/customer_group');
$filter_data = array(
'filter_name' => $this->request->get['filter_name'],
'sort' => 'name',
'order' => 'ASC',
'limit' => 5
);
$this->load->model('catalog/product');
$results = $this->model_catalog_product->getProducts($filter_data);
foreach ($results as $result) {
$json[] = array(
'product_id' => $result['product_id'],
'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8'))
);
}
}
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}
admin/view/template/customer/customer_group_form.twig
<div class="form-group">
<label class="col-sm-2 control-label" for="input-product"><span data-toggle="tooltip" title="{{ help_product }}">{{ entry_product }}</span></label>
<div class="col-sm-10">
<input type="text" name="product" value="" placeholder="{{ entry_product }}" id="input-product" class="form-control"/>
<div id="product-customer" class="well well-sm" style="height: 150px; overflow: auto;"> {% for product in products %}
<div id="product-customer{{ product.product_id }}"><i class="fa fa-minus-circle"></i> {{ product.name }}
<input type="hidden" name="products[]" value="{{ product.product_id }}"/>
</div>
{% endfor %}</div>
</div>
</div>
...
<script type="text/javascript"><!--
$('input[name=\'product\']').autocomplete({
'source': function(request, response) {
$.ajax({
url: 'index.php?route=customer/customer_group/autocomplete&user_token={{ user_token }}&filter_name=' + encodeURIComponent(request),
dataType: 'json',
success: function(json) {
json.unshift({
product_id: 0,
name: '{{ text_none }}'
});
response($.map(json, function(item) {
return {
label: item['name'],
value: item['product_id']
}
}));
}
});
},
'select': function(item) {
$('input[name=\'product\']').val('');
$('#product-customer' + item['value']).remove();
$('#product-customer').append('<div id="product-customer' + item['value'] + '"><i class="fa fa-minus-circle"></i> ' + item['label'] + '<input type="hidden" name="products[]" value="' + item['value'] + '" /></div>');
}
});
$('#product-customer').delegate('.fa-minus-circle', 'click', function() {
$(this).parent().remove();
});
//--></script>
admin/model/customer/customer_group.php
public function getProduct($product_id) {
$query = $this->db->query("SELECT DISTINCT *, pd.name AS name, p.image, m.name AS manufacturer, (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special, (SELECT points FROM " . DB_PREFIX . "product_reward pr WHERE pr.product_id = p.product_id AND pr.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "') AS reward, (SELECT ss.name FROM " . DB_PREFIX . "stock_status ss WHERE ss.stock_status_id = p.stock_status_id AND ss.language_id = '" . (int)$this->config->get('config_language_id') . "') AS stock_status, (SELECT wcd.unit FROM " . DB_PREFIX . "weight_class_description wcd WHERE p.weight_class_id = wcd.weight_class_id AND wcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS weight_class, (SELECT lcd.unit FROM " . DB_PREFIX . "length_class_description lcd WHERE p.length_class_id = lcd.length_class_id AND lcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS length_class, (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT COUNT(*) AS total FROM " . DB_PREFIX . "review r2 WHERE r2.product_id = p.product_id AND r2.status = '1' GROUP BY r2.product_id) AS reviews, p.sort_order FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) LEFT JOIN " . DB_PREFIX . "manufacturer m ON (p.manufacturer_id = m.manufacturer_id) WHERE p.product_id = '" . (int)$product_id . "' AND pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'");
if ($query->num_rows) {
return array(
'product_id' => $query->row['product_id'],
'name' => $query->row['name'],
'description' => $query->row['description'],
'meta_title' => $query->row['meta_title'],
'meta_description' => $query->row['meta_description'],
'meta_keyword' => $query->row['meta_keyword'],
'tag' => $query->row['tag'],
'model' => $query->row['model'],
'sku' => $query->row['sku'],
'upc' => $query->row['upc'],
'ean' => $query->row['ean'],
'jan' => $query->row['jan'],
'isbn' => $query->row['isbn'],
'mpn' => $query->row['mpn'],
'location' => $query->row['location'],
'quantity' => $query->row['quantity'],
'stock_status' => $query->row['stock_status'],
'image' => $query->row['image'],
'manufacturer_id' => $query->row['manufacturer_id'],
'manufacturer' => $query->row['manufacturer'],
'price' => ($query->row['discount'] ? $query->row['discount'] : $query->row['price']),
'special' => $query->row['special'],
'reward' => $query->row['reward'],
'points' => $query->row['points'],
'tax_class_id' => $query->row['tax_class_id'],
'date_available' => $query->row['date_available'],
'weight' => $query->row['weight'],
'weight_class_id' => $query->row['weight_class_id'],
'length' => $query->row['length'],
'width' => $query->row['width'],
'height' => $query->row['height'],
'length_class_id' => $query->row['length_class_id'],
'subtract' => $query->row['subtract'],
'rating' => round($query->row['rating']),
'reviews' => $query->row['reviews'] ? $query->row['reviews'] : 0,
'minimum' => $query->row['minimum'],
'sort_order' => $query->row['sort_order'],
'status' => $query->row['status'],
'date_added' => $query->row['date_added'],
'date_modified' => $query->row['date_modified'],
'viewed' => $query->row['viewed']
);
} else {
return false;
}
}
public function getProducts($data = array()) {
$sql = "SELECT pd.name, p.product_id FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store pts ON (p.product_id = pts.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND pts.store_id = '" . (int)$this->config->get('config_store_id') . "'";
if (!empty($data['filter_name'])) {
$sql .= " AND pd.name LIKE '%" . $this->db->escape($data['filter_name']) . "%'";
}
$sql .= " GROUP BY p.product_id";
$sort_data = array(
'name',
'sort_order'
);
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
$sql .= " ORDER BY " . $data['sort'];
} else {
$sql .= " ORDER BY sort_order";
}
if (isset($data['order']) && ($data['order'] == 'DESC')) {
$sql .= " DESC";
} else {
$sql .= " ASC";
}
$query = $this->db->query($sql);
return $query->rows;
}

if you need autocomplete for customer group, why you querying products?
For customer group add function to the controller, for example to the new your module file: admin/controller/extension/module/customer_group_module.php
public function autocomplete() {
$json = array();
if (isset($this->request->get['filter_customer_group'])) {
$this->load->model('customer/customer_group');
$results = $this->model_customer_customer_group->getCustomerGroups();
foreach ($results as $result) {
$json[] = array(
'customer_group_id' => $result['customer_group_id'],
'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8'))
);
}
}
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}
To this file also add to the public function index() section this:
$data['user_token'] = $this->session->data['user_token'];
if (isset($this->request->post['customer_group_module_customer_group'])) {
$data['customer_group_module_customer_group'] = $this->request->post['customer_group_module_customer_group'];
} elseif ($this->config->get('customer_group_module_customer_group')) {
$data['customer_group_module_customer_group'] = $this->config->get('customer_group_module_customer_group');
} else {
$data['customer_group_module_customer_group'] = array();
}
$data['customer_groups'] = array();
$this->load->model('customer/customer_group');
foreach ($data['customer_group_module_customer_group'] as $customer_group_id) {
$customer_group_info = $this->model_customer_customer_group->getCustomerGroup($customer_group_id);
if ($customer_group_info) {
$data['customer_groups'][] = array(
'customer_group_id' => $customer_group_info['customer_group_id'],
'name' => $customer_group_info['name']
);
}
}
Next you not need to create any model file to get customer groups just use existing and load it as you can see above:$this->load->model('customer/customer_group');
In you template file admin/view/template/extension/module/customer_group_module.twig add:
<div class="form-group">
<label class="col-sm-2 control-label" for="customer-group"><span data-toggle="tooltip" title="{{ help_customer_group }}">{{ entry_customer_group }}</span></label>
<div class="col-sm-10">
<input type="text" name="customer_group" value="" placeholder="{{ entry_customer_group }}" id="customer-group" class="form-control" />
<div id="module-customer-group" class="well well-sm" style="height: 150px; overflow: auto;">
{% for customer_group in customer_groups %}
<div id="customer-group{{ customer_group['customer_group_id'] }}"><i class="fa fa-minus-circle"></i> {{ customer_group['name'] }}
<input type="hidden" name="customer_group_module_customer_group[]" value="{{ customer_group['customer_group_id'] }}" />
</div>
{% endfor %}
</div>
</div>
</div>
And before {{ footer }} add jquery for customer groups not for product:
<script type="text/javascript"><!--
$('input[name="customer_group"]').autocomplete({
source: function(request, response) {
$.ajax({
url: 'index.php?route=extension/module/customer_group_module/autocomplete&user_token={{ user_token }}&filter_customer_group=' + encodeURIComponent(request),
dataType: 'json',
success: function(json) {
response($.map(json, function(item) {
return {
label: item['name'],
value: item['customer_group_id']
}
}));
}
});
},
select: function(item) {
$('input[name=\'customer_group\']').val('');
$('#module-customer-group' + item['value']).remove();
$('#module-customer-group').append('<div id="module-customer-group' + item['value'] + '"><i class="fa fa-minus-circle"></i> ' + item['label'] + '<input type="hidden" name="customer_group_module_customer_group[]" value="' + item['value'] + '" /></div>');
}
});
$('#module-customer-group').delegate('.fa-minus-circle', 'click', function() {
$(this).parent().remove();
});
//--></script>
This is tested and working.

Related

this plugin works only on page

I have a large amount of password-protected posts, all of which are hidden from the average viewer. I’d like a single password entry page to unlock the visibility of all the protected content, as well as a custom landing page after the successful password entry. This plugin seems to do what i’m looking for but only with Pages
can it also work on post and woocomerce products?
i added 'post' in 119 line, but not works
thanks
<?php
/*
define( 'SECONDS_TO_STORE_PW', 864000); // 864000 = 10 Days
class smartPWPages {
function smartpwpages_shortcode( $atts ) {
global $post;
extract( shortcode_atts( array(
'label' => __( 'Enter', 'smartpwpages' ),
'ID' => 'smartPWLogin',
'parent' => $post->ID,
), $atts ) );
$result = '<form ID="' . esc_attr( $ID ) . '" method="post" action="' . esc_url( get_permalink() ) . '" >' . PHP_EOL;
if ( isset( $_GET['wrongpw'] ) ) $result .= '<p id="smartPWError">' . __( 'You\'ve entered an invalid password.</p>', 'smartpwpages' ) . PHP_EOL;
$result .= ' <input class="requiredField" type="password" name="smartPassword" id="smartPassword" value=""/>' . PHP_EOL;
$result .= ' <input type="hidden" name="smartParent" value="' . (int) $parent . '" />' . PHP_EOL;
$result .= ' <input type="hidden" name="smartPWPage_nonce" value="' . wp_create_nonce( 'smartPWPage' ).'" />' . PHP_EOL;
$result .= ' <input type="submit" value="' . esc_attr( $label ). '" />' . PHP_EOL;
$result .= '</form>' . PHP_EOL;
return $result;
}
/**
* Password Redirect
* Decodes the password, stores it in a cookie and redirects the visitor to that page.
*/
function pw_redirect( $perma, $password ) {
global $wp_version, $wp_hasher;
// Version 3.6 introduces a new function
if ( function_exists( 'wp_unslash' ) ) {
$cookiePW = wp_unslash( $password );
} else {
$cookiePW = stripslashes( $password );
}
// Version 3.4 and higher has better security on the pw pages
if ( version_compare( $wp_version, '3.4', '>=' ) ) {
if ( empty( $wp_hasher ) ) {
// By default, use the portable hash from phpass
require_once( ABSPATH . 'wp-includes/class-phpass.php');
$wp_hasher = new PasswordHash( 8, true );
}
// Potentially using a custom hasher, hash the pw
$cookiePW = $wp_hasher->HashPassword( $cookiePW );
}
$secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) );
// Store password for the length in the constant
setcookie( 'wp-postpass_' . COOKIEHASH, $cookiePW, time() + SECONDS_TO_STORE_PW, COOKIEPATH, COOKIE_DOMAIN, $secure );
wp_safe_redirect( $perma );
exit();
}
/**
* Process Form
* Decodes the password submitted on a form, find a page that uses it and redirects the visitor to that page.
*/
function process_form() {
global $wp_version, $wp_hasher;
if ( isset( $_POST[ 'smartPassword' ] ) && isset( $_POST[ 'smartParent' ] ) && wp_verify_nonce( $_POST[ 'smartPWPage_nonce' ], 'smartPWPage' ) ) {
$parentForm = (int) $_POST[ 'smartParent' ] ;
$password = $_POST[ 'smartPassword' ];
if ( function_exists( 'wp_unslash' ) ) {
$postPassword = wp_unslash( $password );
} else {
$postPassword = stripslashes( $password );
}
$args = array(
'sort_order' => 'DESC',
'sort_column' => 'post_date',
'hierarchical' => 1,
'post_type' => 'page','post',
'post_status' => 'publish'
);
if ( function_exists( 'pause_exclude_pages' ) ) pause_exclude_pages();
$myPages = get_pages( $args );
if ( function_exists( 'resume_exclude_pages' ) ) resume_exclude_pages();
// Version 3.4 and higher has better security on the pw pages
if ( version_compare( $wp_version, '3.4', '>=' ) ) {
if ( empty( $wp_hasher ) ) {
// By default, use the portable hash from phpass
require_once( ABSPATH . 'wp-includes/class-phpass.php' );
$wp_hasher = new PasswordHash( 8, true );
}
}
foreach( $myPages as $page ) {
if ( ( $page->post_password == $postPassword ) || ( !empty( $wp_hasher ) &&
$wp_hasher->CheckPassword( $page->post_password, $postPassword ) ) ) {
$permalink = get_permalink( $page->ID );
$this->pw_redirect( $permalink, $postPassword );
}
}
// Nothing more to do here. If we reached here, we've submitted a pw but no match was found.
// Allow the page to continue loading, but hack $_GET to indicate the status
$_GET[ 'wrongpw' ] = TRUE;
}
}
}
) );
thanks to everyone can help me

Dynamic Country - city select on form

newbie alert,
I am really enjoying perl Catalyst, however, i have googled and cant find a solution for Country - City dynamic selection. when i select a country from the dropdown, i would like the cities to change to that coutries cities only. How can i achieve this in Perl, Catalyst using HTML::FormHandler.
PS
The data is coming from mysql db with a one to many relatioship
has_field 'city_id' => (
label => 'City',
type => 'Select',
empty_select => 'Choose city',
required => 1,
required_message => 'Please enter city.',
);
has_field 'country_code' => (
label => 'Country',
type => 'Select',
empty_select => 'Choose country',
required => 1,
required_message => 'Please enter your country.',
);
has_field 'submit' => (
type => 'Submit',
value => 'Save',
element_class => ['btn']
);
sub options_country_code {
my $self = shift;
return unless $self->schema;
my #countries = $self->schema->resultset('Country')->all;
my #options = map { { value => $_->country_code, label => $_->country_name } } #countries;
unshift #options, { value => 0, label => 'Choose Country' };
return #options;
}
__PACKAGE__->meta->make_immutable;
1;
I found exactly what I was looking for, thank you for the effort, I appreciate it very much.
The solution I needed is here
I am using this code as my base:
<html>
<head>
<script type="text/javascript">
function setmenu2() {
var menu1 = document.getElementById('menu1');
var sel = menu1.options[menu1.selectedIndex].text;
var menu2 = document.getElementById('menu2');
if (sel == "Foo") {
menu2.innerHTML = "<option>Foo-1</option>"
+"<option>Foo-2</option>";
} else {
menu2.innerHTML = "<option>Bar-1</option>"
+"<option>Bar-2</option>"
+"<option>Bar-3</option>";
}
}
</script>
</head>
<body>
<select id="menu1" onchange="setmenu2()">
<option>please select...</option>
<option>Foo</option>
<option>Bar</option>
</select>
<select id="menu2">
<option>- ?? -</option>
</select>
</body>
</html>
So far this is what I have:
<script type="text/javascript">
function setcities() {
var country_select = document.getElementById('country_code');
var sel = country_select.options[country_select.selectedIndex].value;
var city_select = document.getElementById('city_id');
if (sel == "AFG") {
city_select.innerHTML = "<option value='1' id='city_id.1'>Kabul</option>"
+"<option value='2' id='city_id.2'> Qandahar</option>";
} else if (sel == "AGO"){
city_select.innerHTML = "<option value='56' id='city_id.1'>Luanda</option>"
+"<option value='57' id='city_id.2'>Huambo</option>"
+"<option value='58' id='city_id.3'>Lobito</option>";
} else {
city_select.innerHTML = "<option>nothing</option>";
}
}
</script>
<select id="country_code" onchange="setcities()">
<option value="" id="country_code.0">please select...</option>
<option value="AFG" id="country_code.1">Afghanistan</option>
<option value="AGO" id="country_code.2">Angola</option>
<option value="AIA" id="country_code.3">Anguilla</option>
</select>
<select id="city_id">
<option>- ?? -</option>
</select>

How to get List for Contact Form 7

I have 2 contact forms created by Contact Form 7.
How to list all contact forms created through shortcode?
Please check images, tks.
Updated:
this is my code, this working!
$args = array('post_type' => 'wpcf7_contact_form', 'posts_per_page' => -1);
$rs = array();
if( $data = get_posts($args)){
foreach($data as $key){
$rs[$key->ID] = $key->post_title;
}
}else{
$rs['0'] = esc_html__('No Contact Form found', 'text-domanin');
}
Below is a dropdown list:
<select name="field-name" id="field-id">
<option value="">--Select--</option><?php
$dbValue = get_option('field-name'); //example!
$posts = get_posts(array(
'post_type' => 'wpcf7_contact_form',
'numberposts' => -1
));
foreach ( $posts as $p ) {
echo '<option value="'.$p->ID.'"'.selected($p->ID,$dbValue,false).'>'.$p->post_title.' ('.$p->ID.')</option>';
} ?>
</select>

Isotope with Fancybox filtering

I implemented Isotope.js into my WordPress site. I use it to display gallery with Easy Fancybox plugin to add zooming functionality for images. Problem is with Isotope filtering. I added rel attribute to my images but when I filter categories Fancybox still cycles through all images.
I need to add rel attribute dynamically based on category I'm filtering. I'm struggling with this problem for 3 days now. I've read bunch of post, tried view things but still can't make it work.
Most of posts give solution with data-fancybox-group attribute but I can't use it I must use rel attribute (it doesn't work for me anyway).
Here's my WP code:
<ul id="filters">
<li>All</li>
<?php
$terms = get_terms("polygraphy-categories");
$count = count($terms);
if ( $count > 0 ){
foreach ( $terms as $term ) {
echo "<li><a class='filterbutton' href='#' data-filter='.".$term->slug."'>" . $term->name . "</a></li>\n";
}
}
?>
</ul>
<?php $the_query = new WP_Query( 'post_type=polygraphy' ); ?>
<?php if ( $the_query->have_posts() ) : ?>
<div id="isotope-list">
<?php while ( $the_query->have_posts() ) : $the_query->the_post();
$termsArray = get_the_terms( $post->ID, "polygraphy-categories" );
$termsString = "";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug.' ';
}
?>
<div class="<?php echo $termsString; ?> poli">
<?php
if ( has_post_thumbnail()) {
$full_image_url = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full');
echo '<a class="fancybox" href="' . $full_image_url[0] . '" title="' . the_title_attribute('echo=0') . '" >';
the_post_thumbnail('thumbnail');
echo '</a>';
}
?>
</div>
<?php endwhile; ?>
</div>
<?php endif; ?>
And JS code:
jQuery(function ($) {
$(window).load(function(){
var $container = $('#isotope-list');
$container.isotope({
itemSelector : '.poli',
layoutMode : 'masonry'
});
var $optionSets = $('#filters'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function(){
var $this = $(this);
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('#filters');
$optionSets.find('.selected').removeClass('selected');
$this.addClass('selected');
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
});
});
I was told that this code should work but it doesn't:
$('.filterbutton').on("click", function(){
var selector = $(this).attr('data-filter');
if(selector == "*"){
$(".fancybox").attr("rel", "gallery");
} else{
$(selector).find(".fancybox").attr("rel", selector);
}
return false;
});

zend-form select optgroup, how to specify id

Hello i am using Zend Framework Form and have tried to get this example to work http://framework.zend.com/issues/browse/ZF-8252, but it fails xD
this is my code
$options = Array
(
[] => Qualsiasi Agente
[agenti_attivi] => Array
(
[4] => Giovanni Abc
[10] => Luigi Abc
[13] => Michela Abc
)
);
$agenti->addMultiOptions($options);
and the generated code is :
<select name="agente_id" id="agente_id" tabindex="6">
<option value="" label="Qualsiasi Agente" selected="selected">Qualsiasi Agente</option>
<optgroup id="agente_id-optgroup-Agenti attivi: " label="Agenti attivi: ">
<option value="4" label="Giovanni Abc">Giovanni Abc</option>
<option value="10" label="Luigi Capoarea">Luigi Abc</option>
<option value="13" label="Michela Abc">Michela Abc</option>
</optgroup>
</select>
where id="agente_id-optgroup-Agenti attivi: " is not xhtml valid Line 724, Column 44: value of attribute "id" must be a single token
i am using zend 1.11.10
thanks
Create a custom view helper FormSelect that extends the core FormSelect and then modify the code.
Include the path to your view helpers in the bootstrap file
protected function _initHelpers()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath('My/View/Helper', 'My_View_Helper');
}
The custom view helper. It's a copy of Zend_View_Helper_FormSelect but with small modification.
class My_View_Helper_FormSelect extends Zend_View_Helper_FormSelect
{
public function formSelect($name, $value = null, $attribs = null,
$options = null, $listsep = "<br />\n")
{
$info = $this->_getInfo($name, $value, $attribs, $options, $listsep);
extract($info); // name, id, value, attribs, options, listsep, disable
// force $value to array so we can compare multiple values to multiple
// options; also ensure it's a string for comparison purposes.
$value = array_map('strval', (array) $value);
// check if element may have multiple values
$multiple = '';
if (substr($name, -2) == '[]') {
// multiple implied by the name
$multiple = ' multiple="multiple"';
}
if (isset($attribs['multiple'])) {
// Attribute set
if ($attribs['multiple']) {
// True attribute; set multiple attribute
$multiple = ' multiple="multiple"';
// Make sure name indicates multiple values are allowed
if (!empty($multiple) && (substr($name, -2) != '[]')) {
$name .= '[]';
}
} else {
// False attribute; ensure attribute not set
$multiple = '';
}
unset($attribs['multiple']);
}
// now start building the XHTML.
$disabled = '';
if (true === $disable) {
$disabled = ' disabled="disabled"';
}
// Build the surrounding select element first.
$xhtml = '<select'
. ' name="' . $this->view->escape($name) . '"'
. ' id="' . $this->view->escape($id) . '"'
. $multiple
. $disabled
. $this->_htmlAttribs($attribs)
. ">\n ";
// build the list of options
$list = array();
$translator = $this->getTranslator();
foreach ((array) $options as $opt_value => $opt_label) {
if (is_array($opt_label)) {
$opt_disable = '';
if (is_array($disable) && in_array($opt_value, $disable)) {
$opt_disable = ' disabled="disabled"';
}
if (null !== $translator) {
$opt_value = $translator->translate($opt_value);
}
$opt_id = ' id="' . $this->formatElementId($id . '-optgroup-' . $opt_value) . '"';
$list[] = '<optgroup'
. $opt_disable
. $opt_id
. ' label="' . $this->view->escape($opt_value) .'">';
foreach ($opt_label as $val => $lab) {
$list[] = $this->_build($val, $lab, $value, $disable);
}
$list[] = '</optgroup>';
} else {
$list[] = $this->_build($opt_value, $opt_label, $value, $disable);
}
}
// add the options to the xhtml and close the select
$xhtml .= implode("\n ", $list) . "\n</select>";
return $xhtml;
}
private function formatElementId($id)
{
// in here put whatever filter you want for the id value
$id = trim(strtr($id, array('[' => '-', ']' => '', ' ' => '', ':' => '')), '-');
$id = strtolower($id);
return $id;
}
}
Done. Create multi select element with a valid id.
<?php
$this->addElement('multiSelect', 'agente_id', array(
'label' => 'Label Name:',
'multiOptions' => array(
'' => 'Qualsiasi Agente',
'Agenti attivi: ' => array(
4 => 'Giovanni Verdi',
10 => 'Luigi Capoarea',
13 => 'Michela Passarin',
)
)
));
try this, it's works for me:
$select = new Zend_Form_Element_Select('select');
$options = Array(
'' => 'Qualsiasi Agente',
'agenti_attivi' => Array(
4 => 'Giovanni Verdi',
10 => 'Luigi Capoarea',
13 => 'Michela Passarin'
)
);
$this->addElements(array($xxxx,$select,$yyyy)); // $this : the form instance
and the result is:
<select id="select" name="select">
<option label="Qualsiasi Agente" value="">Qualsiasi Agente</option>
<optgroup label="agenti_attivi">
<option label="Giovanni Verdi" value="4">Giovanni Verdi</option>
<option label="Luigi Capoarea" value="10">Luigi Capoarea</option>
<option label="Michela Passarin" value="13">Michela Passarin</option>
</optgroup>
</select>
the problem is that the id attribute does not accept spaces and special special characters:
id="agente_id-optgroup-Agenti attivi: "
Zend is usually pretty good about rendering the proper html, given a doctype.
Try setting your doctype like this if you aren't already.
<?php
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$viewRenderer->initView();
$viewRenderer->view->doctype('XHTML1_STRICT');
AND
<?php echo $this->doctype(); ?>
at the top of your layout
I don't have a install of ZF i can mess with easy, if this doesn't work ill setup a test environment.