⚠ In case you've missed it, we have migrated to our new website, with a brand new forum. For more details about the migration you can read our blog post for website migration. This is an archived forum. ⚠

  •     

profile picture

set_relation_n_n and multiple selection



Jim_Nastiq

Jim_Nastiq
  • profile picture
  • Member

Posted 27 March 2012 - 20:00 PM

Hi there,

first thx for the work! great tool!

Is there a way to use a n-n relation plugin and manage multiple selection ?
For example i have a command table , a product table and relation table between them (n-n relation). I would like to be able to add x times a product on a command, but with the plugin after a choixe the product is not available anymore ...

am i missing somethine ?

Thx in advance.

web-johnny

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 27 March 2012 - 20:54 PM

No till this version. I am sorry. I have it though in my long-term plans.

Jim_Nastiq

Jim_Nastiq
  • profile picture
  • Member

Posted 27 March 2012 - 20:58 PM

Thx for fast reply...

any clue where/how i can handle/add this feature ? do you know a jquery plugin that would do something like that ?

manny

manny
  • profile picture
  • Member

Posted 28 March 2012 - 00:20 AM

just the same question. Any suggestions? thx in advance.

web-johnny

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 29 March 2012 - 06:47 AM

It's not just a jquery plugin it is much complicated from that. You have do add a different kind of a relation in grocery CRUD. I don't really have any clue for this and I don't know someone to share a similar solution. If I have any news for this I will inform you.

manny

manny
  • profile picture
  • Member

Posted 29 March 2012 - 13:01 PM

yep, i know:)
I've found an ungly one but fast solution. Smth like:


$crud->callback_field('ordered', array($this, '_ordered_field_callback'));



function _ordered_field_callback($value, $oid) {
//print_r($value);
if(is_numeric($oid)) {
$this->db->where('oid', $oid);
$items = $this->db->get('zp_shop_ordered_items');
if($items->num_rows() != 0) {
$items = $items->result_array();
$items_json = array();
foreach($items as $item) {
if($item['item_quantity'] == null) $item['item_quantity'] = 1;
$items_json[$item['iid']] = $item['item_quantity'];
}
$items_json = json_encode($items_json);
}
else $items_json = '{}';
}
else $items_json = '{}';

$data['items_json'] = $items_json;
$data['items'] = $this->db->get('zp_shop_items')->result_array();
$form = $this->load->view('control_panel/orders_hook.php', $data, true); //here's some js for adding and setting qantity

return $form;
}


in short:
1. callback changes the field, ignoring value. the value in the hidden field is set in json format (like {"item_id": "quantity"}
2. js thing changes this json object on adding or deleting items
3. another callback unsets the form value and changes data in sql table after saving

can share the full code if anyone need it:)

screenshot:
[img]http://www.webpagescreenshot.info/i/789156-329201225953pm.png[/img]

Jim_Nastiq

Jim_Nastiq
  • profile picture
  • Member

Posted 05 April 2012 - 16:14 PM

Hi Manny,

Is it possible to share the full code with us ? (i've already pm you) I would appreciate to see your solution in detail :)

Thx

manny

manny
  • profile picture
  • Member

Posted 06 April 2012 - 19:38 PM

sorry, havent't recieved email 'bout pm)

here's the view:


[color=#008800]orders_hook.php[/color]


<input type="hidden" name="ordered_json" id="ordered-multiselect" value='<?=$items_json?>' />
<span style="display: inline-block; width: 523px; font-size: 18px; padding-left: 8px;">Корзина:</span>
<script>
var result = $.parseJSON($('#ordered-multiselect').val());

var zp_shop_items = <?=json_encode($items)?>;
var zsi_select_box = $("<ul />");
zsi_select_box
.css('display', 'inline-block')
.width(512)
.height(300)
.css('overflow-y', 'scroll')
.css('border-radius', '4px')
.css('border', '1px solid lightGrey')
.css('padding', '3px')
.css('margin', '5px')
.addClass('zsi_select_box');
$.each(zp_shop_items, function(i, val) {
var this_qnty = 0;
if(result[val.iid] != undefined) this_qnty = result[val.iid];

zsi_select_box.append('<li class="zsi-item"><span>'+val.item_title+'</span>'+
'<input value="+" class="plusbtn" type="button" onclick="iplus(this); return false;" />'+
'<input class="zsi-item-qnty" value="'+this_qnty+'" rel="'+val.iid+'" type="text" onkeyup="countItemsToOrder(this);" style="width: 32px; float: right;" />'+
'<input value="&minus;" class="minusbtn" type="button" onclick="iminus(this); return false;" />'+
'</li>');
});

var zsi_qsearch = $('<input type="text" />');
zsi_qsearch.attr('placeholder', 'Быстрый поиск');

jQuery.expr[':'].Contains = function(a, i, m) {
return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
}; //case insensetive :contains func;
zsi_qsearch.keyup(function() {
zsi_select_box.children('li').css('display', 'none');
zsi_select_box.children('li:Contains("'+zsi_qsearch.val()+'")').css('display', 'block');
});

var zsi_selected_box = $('<ul />');
zsi_selected_box
.css('display', 'inline-block')
.width(512)
.height(300)
.css('overflow-y', 'scroll')
.css('border-radius', '4px')
.css('border', '1px solid lightGrey')
.css('padding', '3px')
.css('margin', '5px')
.addClass('zsi_selected_box');

$('#ordered-multiselect').parent().append(zsi_qsearch);
$('#ordered-multiselect').parent().append('<br />');
$('#ordered-multiselect').parent().append(zsi_selected_box);
$('#ordered-multiselect').parent().append(zsi_select_box);
itemsToSelected();



function countItemsToOrder(inputEl) {
var qnty = $(inputEl).val();
var iid = $(inputEl).attr('rel');
if(qnty > 0) result[iid] = qnty;
else delete result[iid];
$('#ordered-multiselect').val(JSON.stringify(result));
itemsToSelected();
}

function itemsToSelected(result) {
$('li.zsi-item').each(function(i) {
if($(this).children('input.zsi-item-qnty').val() > 0) {
if($(this).parent().attr('class') != zsi_selected_box.attr('class'))zsi_selected_box.prepend(this);
}
else zsi_select_box.append(this);
});

var elems = zsi_select_box.children('li').remove();
elems.sort(function(a,B){
var compA = $(a).text().toUpperCase();
var compB = $(B).text().toUpperCase();
return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
});
zsi_select_box.append(elems);
}

function iplus(btn) {
var val = $(btn).siblings('input.zsi-item-qnty').val();
val = parseInt(val);
if(isNaN(val) || val == '') val = 0;
if(val == 0) {
zsi_qsearch.val('');
zsi_qsearch.trigger('keyup');
}
$(btn).siblings('input.zsi-item-qnty').val(val + 1).trigger('keyup');
}

function iminus(btn) {
var val = $(btn).siblings('input.zsi-item-qnty').val();
val = parseInt(val);
if(isNaN(val) || val == '') val = 0;

if(val > 0) $(btn).siblings('input.zsi-item-qnty').val(val - 1).trigger('keyup');
else $(btn).siblings('input.zsi-item-qnty').val(val).trigger('keyup');
}
</script>

manny

manny
  • profile picture
  • Member

Posted 06 April 2012 - 19:41 PM

Tested in chorome, could be buggy in any other browser.
For example fn [color=#000000][size=2]JSON[/size][/color][color=#666600][size=2].[/size][/color][color=#000000][size=2]stringify [/size][/color]should be replaced. There a lot of jquery libs doing the same.

manny

manny
  • profile picture
  • Member

Posted 06 April 2012 - 19:44 PM

and the controller:


public function orders() {
$this->grocery_crud
->set_subject('заказ')
->set_table('zp_shop_orders')
->columns('oid', 'clid', 'order_status', 'ordered', 'order_created', 'order_last_update')
->add_fields('clid', 'ordered', 'order_last_update', 'order_created')
->edit_fields('clid', 'order_status', 'ordered', 'order_last_update')
->required_fields('clid')

->callback_field('ordered', array($this, '_ordered_field_callback'))

->change_field_type('order_last_update', 'hidden', null)
->change_field_type('order_created', 'hidden', null)

->display_as('oid','ID')
->display_as('clid','Клиент')
->display_as('ordered','Заказ')
->display_as('order_created','Дата заказа')
->display_as('order_last_update','Последнее обновление')
->display_as('order_status','Статус');

$this->grocery_crud->callback_before_insert(array($this, '_add_order_callback'));
$this->grocery_crud->callback_before_update(array($this, '_update_order_callback'));
$this->grocery_crud->callback_after_insert(array($this, '_order_callback_set_clid'));
$this->grocery_crud->callback_after_update(array($this, '_order_callback_set_clid'));

$this->grocery_crud
->set_relation('clid','zp_clients','{client_name} (id: {clid})')
->set_relation_n_n('ordered', 'zp_shop_ordered_items', 'zp_shop_items', 'oid', 'iid', 'item_title')
;

$output = $this->grocery_crud->render();

//print_r($output);

$this->crud_output($output);
}

function _add_order_callback($post) {
//
$time = date("Y-m-d H:i:s");
$post['order_last_update'] = $time;
$post['order_created'] = $time;

//$rand_ind = base_convert(time() - strtotime('01/01/2012'), 10, 32);
//$post['oid'] = $post['clid'].'_'.$rand_ind;
print_r($post);
return $post;
}

function _update_order_callback($post) {
$time = date("Y-m-d H:i:s");
$post['order_last_update'] = $time;
return $post;
}

function _order_callback_set_clid($post, $oid) {
print_r($post);
//$this->db->where('oid', $oid);
//$this->db->update('zp_shop_ordered_items', array('clid' => $post['clid']));

$ordered = json_decode($post['ordered_json'], true);
print_r($ordered);
foreach($ordered as $iid => $qnty) {
$item = $this->db->get_where('zp_shop_ordered_items', array('iid' => $iid, 'oid' => $oid));
if($item->num_rows() != 0) {
$this->db->where(array('iid' => $iid, 'oid' => $oid));
if($qnty != 0) $this->db->update('zp_shop_ordered_items', array('item_quantity' => $qnty, 'clid' => $post['clid']));
else $this->db->delete('zp_shop_ordered_items');
}
else {
if($qnty != 0) $this->db->insert('zp_shop_ordered_items', array('oid' => $oid, 'iid' => $iid, 'item_quantity' => $qnty, 'clid' => $post['clid']));
}
}
}

function _ordered_field_callback($value, $oid) {
//print_r($value);
if(is_numeric($oid)) {
$this->db->where('oid', $oid);
$items = $this->db->get('zp_shop_ordered_items');
if($items->num_rows() != 0) {
$items = $items->result_array();
$items_json = array();
foreach($items as $item) {
if($item['item_quantity'] == null) $item['item_quantity'] = 1;
$items_json[$item['iid']] = $item['item_quantity'];
}
$items_json = json_encode($items_json);
}
else $items_json = '{}';
}
else $items_json = '{}';

$data['items_json'] = $items_json;
$data['items'] = $this->db->get('zp_shop_items')->result_array();
$form = $this->load->view('control_panel/orders_hook.php', $data, true);

return $form;
}

manny

manny
  • profile picture
  • Member

Posted 06 April 2012 - 19:48 PM

css:


li.zsi-item {
background-color: #FAFAFA;
border: 1px solid #CCC;
border-radius: 3px;
box-shadow: rgba(0, 0, 0, 0.0976563) 0px 1px 3px 0px inset;
color: #444;
cursor: auto;
display: block;
height: 33px;
letter-spacing: normal;
margin: 3px;
padding: 5px;
text-align: -webkit-auto;
text-indent: 0px;
text-shadow: none;
vertical-align: baseline;
width: 478px;
word-spacing: 0px;
}
li.zsi-item span{
display: table-cell;
float: left;
vertical-align: middle;
width: 320px;
height: 30px;
overflow: hidden;
}
input.minusbtn, input.plusbtn {
margin: 0 5px;

background-attachment: scroll;
background-clip: border-box;
background-color: #E6E6E6;
background-image: url(../assets/grocery_crud/css/ui/simple/images/ui-bg_glass_75_e6e6e6_1x400.png);
background-origin: padding-box;
border-radius: 4px;
border: 1px solid lightGrey;
box-sizing: border-box;
color: #555;
cursor: pointer;
display: inline-block;
float: right;
font-family: Verdana, Arial, sans-serif;
font-size: 15px;
font-weight: normal;
height: 32px;
letter-spacing: normal;
line-height: normal;
overflow-x: visible;
overflow-y: visible;
padding-bottom: 6px;
padding-left: 15px;
padding-right: 15px;
padding-top: 6px;
position: relative;
text-align: center;
text-decoration: none;
text-indent: 0px;
text-shadow: none;
text-transform: none;
vertical-align: baseline;
white-space: pre;
word-spacing: 0px;
zoom: 1;
}
input.minusbtn:hover, input.plusbtn:hover {
border: 1px solid #999;
color: #000;
background-image: url(../assets/grocery_crud/css/ui/simple/images/ui-bg_glass_75_dadada_1x400.png);

}
.zsi_select_box input.minusbtn, .zsi_select_box input.zsi-item-qnty {
display: none!important;
}

Jim_Nastiq

Jim_Nastiq
  • profile picture
  • Member

Posted 07 April 2012 - 08:33 AM

Thx Manny :)

I'll try to test it !

rdroguett

rdroguett
  • profile picture
  • Member

Posted 11 July 2012 - 18:31 PM

Great!

It's possible post the database struct...