Joomla (3.x) custom form field type:text with suggestion dropdown - joomla-extensions

I'm try'n to create a custom form field of type text (or list) where a user can a) type free text and/or b) select from drop-down. Now I found many posts about autocomplete or auto-fill, but that's not what I'm after.
I followed the example on how to create a 'City' Custom field here http://docs.joomla.org/J2.5:How_to_add_custom_filters_to_components and this is all working.
However, it creates a drop-down only, no option to enter text.
I'm new to the Joomla (3.x) component development, so maybe I am missing something very simple here. With all those field types available, it's hard to belief there is no drop-down with free input.
So
1. can I make the default select/list to accept free text?
2. if not, can I get a pointer on how to get started making one my self?
3. For now, it would be fine to have ~10 city names listed, and free input, no need to filter the city list while typing. But ultimately, I would like to know on how to create a filter while typing Ajax version of this. (Like a suggest input-box)
This is what I use at the moment, the example as linked above
I also tried extending Jformfield, with no luck
class JFormFieldCftCity extends JFormFieldList {
protected $type = 'CftCity';
public function getOptions() {
$options = array();
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('value As value, name As text');
$query->from('#__bitLuCity AS a');
$query->order('a.sortOrder');
$query->where('isEnabled = 1');
$db->setQuery($query);
$options = $db->loadObjectList();
return $options;
}
}
Thanks
Regards
Andreas

For anyone in the same position and future reference I'm going to post my own solution here as I ended up not using #isherwood's suggestion. I have not yet figured out completely how to integrate 'select2' into my component, nor is it needed for simple 'combobox' behavior.
This is HTML5 only, no additional script's, extends a plain JFormField.
It will allow free input, as well as select from the static list and filters while typing.
class JFormFieldCftCity extends JFormField {
protected $type = 'CftCity';
public function getInput() {
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('value As value, name As text');
....
$db->setQuery($query);
$rows = $db->loadObjectList();
$control= '<input id="' . $this->id . '" name="' . $this->name
. '" list="dataSrc-'. $this->id .'" value="' . $this->value
. '" type="text" class="inputbox" />'
. '<datalist id="dataSrc-'. $this->id .'">';
for ($i = 0; $i < count($rows); $i++) {
$control .= "<option value='{$rows[$i]->text}'>{$rows[$i]->text}/option>";
}
$control .= '</datalist>';
return $control;
}

It did not work in Safari, but I finally found a solution that works in all browsers, until datalist HTML5 markup is supported by all browsers:
<input type="text" class="span6 " style="margin: 0 auto;" data-provide="typeahead" data-items="4" data-source="["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]" />
You can of course fill "data-source" with data from your query.

Related

yii2 search in gridview encrypted data (searchModel)

Little question, i had to encrypt the "name" field in my table... but, i need to be able to do a searrch with the gridview...
And this, does not work :
query->andFilterWhere(['like', 'name', $this->decryptData($this->name)]);
Just to say, i have a decryptData() and encryptData() in my model. The encryption/decryption works everwhere, just not on the filter.
if i do
query->andFilterWhere(['like', 'name', $this->encryptData($this->name)]);
i don't get any result in the gridview even without any search
any idea how to search in encrypt data ?
Thank you very much !
EDIT:
#MuhammadOmerAslam #MichalHynčica ,
this what i do in my model :
public function encryptData($data){
$secretKey = '23jks2k4js82kj';
$encrypted = utf8_encode(Yii::$app->security->encryptByKey($data, $secretKey));
$key = $encrypted;
return $key;
}
public function decryptData($data){
$secretKey = '23jks2k4js82kj';
$decrypted = Yii::$app->security->decryptByKey(utf8_decode($data), $secretKey);
$key = $decrypted;
return $key;
}
i need to be able to type for example : Vir and that the rows with Virginie, or Virginia, or Viridontknowwhat will show.
Whould it be possible to decrypt the datas in an array, then search in it ?
or would it be better to do a search with jQuery on the gridview as the datas are decrypted in the gridview ?
I was trying this but can't stop the gridview to send the datas to the searchModel.
Thank you for your help !

woocommerce get attribute terms

In Woocommerce you can add global product attributes and terms. So for instance:
Size (attribute)
small (term)
medium (term)
large (term)
This is product independent. You can then select from the pre defined attributes on a product.
I need to get all of the terms in an attribute with php. So select the attribute required, eg size, and then return an array including [small,medium,large].
Seems simple enough but I can't find any help on doing this.
Slightly confusing, especially when looking through the WooCommerce Docs since there is absolutely no mention of getting a list of the terms/attributes.
The Attributes are saved as a custom taxonomy, and the terms are taxonomy terms. That means you can use native Wordpress functions: Wordpress get_terms() Function Reference
By clicking on an attribute in WooCommerce, you can look in the URL and you can see they are all prepended with 'pa_'
This is likely what you need:
$terms = get_terms("pa_size");
foreach ( $terms as $term ) {
echo "<option>" . $term->name . "</option>";
}
I wanted to be able to get all the different attributes from the backend that were set, and get them in an array for me to work with, I took some code from the class-wc-admin-attributes.php file and modified it for my needs:
<?php
$attribute_taxonomies = wc_get_attribute_taxonomies();
$taxonomy_terms = array();
if ($attribute_taxonomies) :
foreach ($attribute_taxonomies as $tax) :
if (taxonomy_exists(wc_attribute_taxonomy_name($tax->attribute_name))) :
$taxonomy_terms[$tax->attribute_name] = get_terms(wc_attribute_taxonomy_name($tax->attribute_name), 'orderby=name&hide_empty=0');
endif;
endforeach;
endif;
var_dump($taxonomy_terms);
exit;
This will loop through all the attribute taxonomies, retrieve the terms for each, leaving you with an array of term objects to work with for each taxonomy.
Since 4.5.0, taxonomies should be passed via the ‘taxonomy’ argument in the $args array:
$terms = get_terms( array(
'taxonomy' => 'pa_taxonyname',
'hide_empty' => false,
) );
For example, if the taxonomy slug is 'date', so the taxonomy will be 'pa_date'.
You can also mouse over the attribute name and see the taxonomy name at the bottom of the browser.
I hope it helps!
I use this:
echo '<h1>variations</h1>';
mario( $product->get_available_variations());
echo '<h1>Atributos</h1>';
mario($product->get_attributes());
echo '<h1>Poste Terms</h1>';
mario(wp_get_post_terms( $post->ID, 'pa_color'));
function mario($texto){
echo '<pre>';var_dump($texto);echo '</pre>';
};
Really with: "wp_get_post_terms( $post->ID, 'pa_color')" i search only one term, but the idea is to loop for the key ['name'] that return that function.
Get all attributes with attribute terms in woocommerce.
$attributes = wc_get_attribute_taxonomies();
foreach ($attributes as $attribute) {
$attribute->attribute_terms = get_terms(array(
'taxonomy' => 'pa_'.$attribute->attribute_name,
'hide_empty' => false,
));
}

On Orchard CMS, how can I display a message when the query returns no records for a projection

Using the admin panel on Orchard CMS I've created the following:
A content type called CalendarEvent, it contains several fields including the EventDate;
A query that has 2 filters, one by the content type (= CalendarEvent) and another one based on the date of the event. The Display Mode on the Layout is set to Properties;
A projection to display the query when a menu item is clicked.
The problem is that based on the EventDate we only display upcoming events, not the ones in the past. If for some reason there are no events to be displayed, all the user gets is an empty page with no information whatsoever.
My question is, how can I modify my query or projection in order to display something like: "There are no current events scheduled"?
I know the Properties on the Query's Layout allow me to specify a "No Result", but this implies that a record is present and that the actual property is empty. However, in my example, no record is present.
Thank you all in advance.
Rafael
By the way, I am using the latest Orchard version 1.6.
What I have done is to create a shape and use it as a view in my query. The shape will then have an if statement to check if the query return gives any results.
Example:
#using Orchard.ContentManagement
#using Orchard.Utility.Extensions
#{
var dealsTerms = ((IEnumerable<ContentItem>)Model.ContentItems).ToList();
}
#if (dealsTerms.Any() )
{
<div>
#foreach (var dealTerm in dealsTerms)
{
var contentManager = dealTerm.ContentManager;
<div>
#Display(contentManager.BuildDisplay(dealTerm, "Summary"))
</div>
}
</div>
}
else
{
<p>No deals found</p>
}
I used this article as reference:
http://www.ideliverable.com/blog/ways-to-render-lists-of-things
Good luck
If your projections are Layouts elements, you can create a Projection.cshtml file in your theme's Views/Elements folder with the following:
#{
var list = Model.List;
var pager = Model.Pager;
if (list != null)
{
#Display(list)
if (list.Items.Count == 0)
{
<div>There are currently no items.</div>
}
}
if (pager != null)
{
#Display(pager)
}
}
This is a copy of the default template with the if (list.Items.Count == 0) section added. Edit as needed.

Drupal autocomplete fails to pull out data as a subdomain

I managed to pull out data using autocomplete at my local (http://mysite.dev/swan/autocomplete). The json data is displayed.
But when I applied the same module at live (now a subdomain: http://test.mysite.com/swan/autocomplete with different drupal installs), this autocomplete fails to pull out data. No json data is displayed.
Do you have any idea if this is related to cross domain issue, or any possible cause I might not be aware of?
This is the callback:
/**
* Callback to allow autocomplete of organisation profile text fields.
*/
function swan_autocomplete($string) {
$matches = array();
$result = db_query("SELECT nid, title FROM {node} WHERE status = 1 AND type='organisation' AND title LIKE LOWER ('%s%%')", $string, 0, 40);
while ($obj = db_fetch_object($result)) {
$title = check_plain($obj->title);
//$matches[$obj->nid] = $title;
$matches[$title] = $title;
}
//drupal_json($matches); // fails at safari for first timers
print drupal_to_js($matches);
exit();
}
Any hint would be very much appreciated.
Thanks
It's the conflict with password_policy.module. Other similar modules just do the same blocking. These modules stop any autocomplete query.

How does one get Drupal's current view/page identifier?

What I am looking for is a page_id/view_id that I can use to identify and style specific pages. I would use the title or the url, but there is a chance that it could change if the a higher-up decides that the page should no longer be called Golf, but rather Tee-Time because he likes it better.
Presumably this identifier would not change if the current page were to be a paged view (page 1,2,3,4...).
One way of solving this is the following. It's depending on the url, so if it changes, so does the class-name.
In my themes template.php I implemented hook_preprocess_page:
function mytheme_preprocess_page(&$vars, $hook) {
$body_classes = array();
$body_classes[] = 'page-' . _get_page_name($_SERVER['REQUEST_URI']);
$vars['body_classes'] = implode(' ', $body_classes);
}
function _get_page_name($request_uri) {
static $numeric_subsection = array(
'/node/' => 'node',
);
$preAlias = $request_uri;
$alias = substr(strrchr($preAlias, "/"), 1);
if (strpos($alias, '?') > -1) {
$alias = substr($alias, 0, strpos($alias, '?'));
}
$page_name = $alias;
if (empty($alias)) {
$page_name = 'start';
}
else if (is_numeric($alias)) {
foreach ($numeric_subsection as $section => $pn) {
if (strpos($preAlias, $section) > -1) {
$page_name = $pn;
}
}
}
return $page_name;
}
Then in the main page-template:
<body class="<?php print $body_classes; ?>">
This isn't a generic solution. So you'll probably have to customize this for your specific needs. It will for example need som tweaking to play nicely with path auto.
This depends a little on how your site is put together (panel pages, view pages, "normal" pages). Essentially, you need to figure out what vars are in scope, and then determine which information in them can be used. To determine what is in scope, you can use print_r(array_keys(get_defined_vars())); and then poke around in the individual vars.
An option is to do something in theme_preprocess_page. One option is to get the page data via page_manager_get_current_page(), poke around in there, and then add body classes as needed. Without knowing what you are doing, you essentially need to print_r the results somewhere, look at what you have, and go from there.

Resources