Use dynamic div IDs with jQuery - javascript

I have a container which is filled with max. 20 items, each item gets its information (such as image) from an SQL database and an own div with id suit_(1-20).
The items get listed in the code below:
<?php
$d = 1;
?>
<table >
<tbody>
<?php while $item = sqlsrv_fetch_object($user_item) : ?>
<td align="center" height="50" width="21%">
<div class="tooltips" href="">
<div class="suitable" id="suit_<?php echo $d++ ?>" name="<?php echo $myDBID ?>">
<img src="images/icon/<?php echo $item->Img ?>">
</div>
</div>
</td>
<?php endwhile; ?>
</tbody>
</table>
As you see each div has the id suit_(d++) which means 1-20 for max 20 items.
Those divs have a jQuery script to trigger a contextual menu event on right click:
$(function () {
var count;
for(count = 1; count < 21; count++) {
var ID = document.getElementById('suit_' + count).getAttribute('id');
$('#suit_' + count).contextPopup({
items : [{
label : 'Set',
action : function () {
window.location.href = "?settest=" + ID
}
},
null,
{
label : 'Throw',
action : function () {
window.location.href = "?throwtest=" + ID
}
},
]
});
}
});
I have a for-loop which should count from 1 to 20 and generate the appropriate ids (suit_1 to suit_20).
Somehow the script works only for the last item in the container, so if I have 10 items in it, all items will get the ID suit_10.
Any ideas?

Why not remove the loop, and use an starts with attribute selector?
Using the ^= selector says "anything that starts with":
// A bit "safer" document ready, won't collide with other libraries that use $
jQuery(function($) {
// Select all items with ID starting with "suit_"
$('[id^="suit_"]').contextPopup({
items : [{
label : 'Set',
action : function () {
window.location.href = "?settest=" + $(this).attr('id');
}
},
null,
{
label : 'Throw',
action : function () {
window.location.href = "?throwtest=" + $(this).attr('id');
}
},
]
});
});

I solved the issue by adding an each(function()) for the selector and setting a variable object before the event starts.
The problem with the previous solution was the child function
action : function () {
window.location.href = "?settest=" + ID
}
which caused that $(this)was not working.
See the full code below:
jQuery(function($) {
$('[id^="suit_"]').each(function(){
var object = this;
$(object).contextPopup({
items : [{
label : 'Set',
action : function () {
window.location.href = "?settest=" + object.id
}
},
null,
{
label : 'Throw',
action : function () {
window.location.href = "?throwtest=" + object.id
}
},
]
});
});
});

Related

Stop .blur() function from triggering on select statement but remain on span

I am trying to create an inline edit function to trigger differently on different elements.
I have tried to use other plugins but haven't been able to get them to do exactly what I want so have decided to try to create a plugin of my own, while learning jquery along the way.
The issue I am currently having is that I have a .blur event that is triggering on a span element correctly and this is what I want but when the element is a select element I don't want the blur event to trigger. As the code is below the blur event triggers and it is not the desired result. Can anybody advise how I can only trigger the blur() event on span elements and nothing else
$('.inlineEdit-jmc').inlineEditJmc({
fieldsArray: {
table-column1: 'field-table-column1',
table-column2: 'field-table-column2'
}
});
(function ( $ ) {
$.fn.inlineEditJmc = function(options) {
//Set Default Settings
console.log(options);
var settings = $.extend({
'pk': null,
'table': null,
'field': null,
'url': null,
'type': null,
'fieldsArray': null
},options)
if(settings.fieldsArray == null){}else{
var fields = new Array();
}
function load_settings(this_selected){
settings['pk'] = this_selected.attr("data-pk"); // pk of table to be updated
settings['table'] = this_selected.attr("data-table"); // table name of table to be updated
settings['field'] = this_selected.attr("data-field"); // name of the field in the table being updated
settings['url'] = this_selected.attr("data-url"); // url for the ajax call to be sent to.
settings['type'] = this_selected.attr("data-type"); // type of input being used. Input or Select
settings['value'] = this_selected.text(); //
settings['class'] = this_selected.attr("class"); // The Class
console.log(settings['table'] +' '+ settings['value']+ ' '+ settings['class']);
// if there are optionional inserts passed lets grab them
console.log('passed options:');
if(settings.fieldsArray == null){}else{
//var fields = [];
$.each(settings.fieldsArray,function(k,v){
//console.log('settings['+k+'] '+this_selected.attr(v));
$obj={};
$obj[k] = this_selected.attr(v);
fields.push($obj);
});
}
}
$(this).on('mouseover', function(event) {
$(this).addClass("ui-state-hover");
}).on('mouseout', function(event) {
$(this).removeClass("ui-state-hover");;
});
if($(this).is('select')){
$(this).on('change', function(){
alert('changed');
alert($(this).val());
//console.log($(this));
//load_settings($(this));
var nt = $(this).text();
var jsonstring = JSON.stringify(fields);
// AJAX
});
}
if($(this).is('span')){
$(this).on("blur", function () {
alert('span');
load_settings($(this));
var nt = settings['value']
console.log('comment: '+settings['value']);
// we are going to update the db here.
console.log('Insert');
console.log(fields);
var jsonstring = JSON.stringify(fields);
console.log(jsonstring);
$.ajax({
type: 'POST',
url: settings['url'],
data: {
fieldsArray: fields,
pk: settings['pk'],
table: settings['table'],
field: settings['field'],
value: settings['value']
},
cache: false,
success: function(data,status){
console.log(data);
}
});
});
}
}
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<td class=''>
<select class='inlineEdit-jmc' ><option value='0' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='ignore'>NO</option>
<option value='1' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='ignore' selected>YES</option>
</select></td>
<td class=''><span class='inlineEdit-jmc' id='input' data-pk='3' data-url='/path/to/js/ajax/ajax.php' data-table='mysqltablename' data-field='comment' contenteditable='true'>Text that can be edited</td>
Try this code section in place of yours that begins if($(this).is('span')){
$(this).on("blur", function ()
$("span").on("blur", function () {
// your function content here
});
$("span select").on("blur", function () {
e.stopPropagation();
});
The two alternative selectors act like a case statement in jQuery

div sort not working when div generated dynamically

I'm trying to sort a list of divs with the properties shown by particular attributes (gender, level, name etc) using the following script:
html:
<div id="sortThis" class="col-xs-12 alert-container">
<div id="1" class="container-element sortable box box-blue" data-gender="1" data-level="4" data-name="AAA"> <h3>AAA</h3><div class="panel-body">AAA is resp</div>
</div>
<div id="2" class="container-element sortable box box-pink" data-gender="2" data-level="3" data-name="DDD"><h3>DDD</h3><div class="panel-body">DDD is a s</div>
</div>
<div id="3" class="container-element sortable box box-blue" data-gender="1" data-level="2" data-name="FFF"><h3>FFF</h3><div class="panel-body">FFF has mad</div>
</div>
<div id="4" class="container-element sortable box box-pink" data-gender="2" data-level="4" data-name="CCC"><h3>CCC</h3><div class="panel-body">CCC has ma</div>
</div>
<div id="5" class="container-element sortable box box-pink" data-gender="2" data-level="2" data-name=EEE><h3>EEE</h3><div class="panel-body">EEE is a f</div>
</div>
<div id="6" class="container-element sortable box box-blue" data-gender="1" data-level="3" data-name="BBB"><h3>BBB</h3><div class="panel-body">BBB is an ou</div>
</div>
</div>
<button id="sLevel" class="LbtnSort">Sort by Level</button><br/>
<button id="sGender" class="GbtnSort">Sort by Gender</button><br/>
js:
var LdivList = $(".box");
LdivList.sort(function(a, b){
return $(a).data("level")-$(b).data("level")
});
var GdivList = $(".box");
GdivList.sort(function(a, b){
return $(a).data("gender")-$(b).data("gender")
});
/* sort on button click */
$("button.LbtnSort").click(function() {
$("#sortThis").html(LdivList);
});
/* sort on button click */
$("button.GbtnSort").click(function() {
$("#sortThis").html(GdivList);
});
when the .sortable divs are static, the sort works fine, as this jfiddle shows, however if the contents of the #sortable div (i.e. .sortable divs) are dynamically generated (in this case as the result of a form submit), when the sort button is pressed, the entire contents of the #sortable div disappears, and I can't seem to get it to work.
Any help or suggestions would be appreciated.
edit: The code for dynamic generation of the list is as follows - effectively it's an AXAX form submit that pulls data from a sorted list of items and outputs them.
$('#formStep2').submit(function(event) {
// get the form data
var studentArray = [];
$(".listbox li").each(function() {
studentArray.push({
'name': ($(this).text()),
'gender': ($(this).closest('ol').attr('id')).substr(0, 1),
'level': ($(this).closest('ol').attr('id')).substr(2, 3),
'topic': ($('input[name=topic]').val())
})
});
var studentString = JSON.stringify(studentArray);
console.log(studentString);
var formData = {
'students': studentString,
};
// process the form
$.ajax({
type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
url: 'process_step2.php', // the url where we want to POST
data: formData, // our data object
dataType: 'json', // what type of data do we expect back from the server
encode: true
})
// using the done promise callback
.done(function(data) {
if (!data.success) {
// error handling to go here.....
} else {
$('.alert-container').empty();
var obj = JSON.parse(data.message);
//sort the array alphabetically by name (default status)
var test = obj.sort(function(a,b){
var lccomp = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
return lccomp ? lccomp : a.name > b.name ? 1 : a.name < b.name ? -1 : 0;
});
console.log(test);
var i=0;
test.forEach(function(st) {
console.log(st['name']);
var gen = (st['gender'] == 1) ? "blue" : (st['gender'] == 2) ? "pink" : NULL;
$('.alert-container').append('<div id="' + (i+1) + '" class="container-element sortable box box-' + gen + '" data-gender="' + st['gender'] + '" data-level="' + st['level'] + '" data-name="' + st['name'] + '"><h3>' + st['name'] + '</h3><div class="panel-body"><div class="col-xs-9"><i class="fa fa-quote-left fa-3x fa-pull-left fa-' + gen + '" aria-hidden=:true"></i>' + st['comment'] + '</div></div></div>');
i++;
});
// jump to the next tab
var $active = $('.wizard .nav-tabs li.active');
$active.next().removeClass('disabled');
nextTab($active);
}
})
// using the fail promise callback
.fail(function(data) {
// show any errors
// best to remove for production
console.log(data);
});
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
You are defining LdivList and GdivList inline with your code so they are defined on DOM ready. You have to wrap the definition of those inside a function and call it on click:
$(document).ready(function(){
$("button.LbtnSort").click(function() {
$("#sortThis").html(GenerateLdivList);
});
/* sort on button click */
$("button.GbtnSort").click(function() {
$("#sortThis").html(GenerateGdivList());
});
});
function GenerateLdivList(){
var LdivList = $(".box");
LdivList.sort(function(a, b){
return $(a).data("level")-$(b).data("level")
});
}
function GenerateGdivList(){
var GdivList = $(".box");
GdivList.sort(function(a, b){
return $(a).data("gender")-$(b).data("gender")
});
}
As #theduke said, the lists are probably empty at the time you sort them. Here's a simple change that will read and sort the lists when you click the buttons instead. (Not tested.)
var LdivList = function () {
return $(".box").sort(function(a, b){
return $(a).data("level")-$(b).data("level")
});
};
var GdivList = function () {
return $(".box").sort(function(a, b){
return $(a).data("gender")-$(b).data("gender")
});
};
/* sort on button click */
$("button.LbtnSort").click(function() {
$("#sortThis").html(LdivList());
});
/* sort on button click */
$("button.GbtnSort").click(function() {
$("#sortThis").html(GdivList());
});

WP Media Library - Select function not updating row index for ID update

I am working on a wordpress blog with a custom metabox on the edit page of each post.
This metabox consists of table with each row containing image src selected from media library.
Now every new row added has an id :
row 1 : img_metabox_src_0
row 2 : img_metabox_src_1
row 3 : img_metabox_src_2
Table headers goes like :
----Image < img >------ |------- URL (Input textbox)------ | -------- Select Image (Input submit)------ | -----Delete Image (Input submit)--------
Now,
On click on "Select Image" on any row, I retrieve the row index from jquery, and then send : "img_metabox_src_"+index to file_frame.on( 'select', function() for url update.
i.e.
jQuery('tr #select_image').off().on('click', function( event ){
event.preventDefault();
var row_index = jQuery(this).closest('tr').index();
var id = "img_metabox_src_" + row_index;
//******** 1 ***********
console.log('row_index');
console.log(row_index);
console.log(id);
console.log(jQuery('#' + id));
if ( file_frame ) {
file_frame.open();
return;
}
file_frame = wp.media.frames.file_frame = wp.media({
title: "Select/Upload Image",
button: {
text: "Select",
},
library : { type : 'image'},
multiple: false
});
file_frame.on( 'select', function() {
attachment = file_frame.state().get('selection').first().toJSON();
// "mca_features_tray" is the ID of my text field that will receive the image
// I'm getting the ID rather than the URL:
// but you could get the URL instead by doing something like this:
//******** 2 ***********
console.log(id);
console.log(jQuery('#' + id));
jQuery('#' + id).attr('value',attachment.url);
id = null;
});
Now,
Case 1 : When I FIRST click with row index3, the URL updates on img_metabox_src_3.
Case 2 : But after that whichever row i click, the url updates on img_metabox_src_3.
Also on adding logs, I get
(for Case 2, say I clicked row index 1) :
//******** 1 ***********
row index : 1
id : img_metabox_src_1
//******** 2 ***********
id : img_metabox_src_3
i.e. inside file_frame.on( 'select', function() {,
the ID value changes to first clicked value.
Please help on how to pass updated row index/id to the select function
Thanks, I used global concept :
function set_row_index (ind){
row_index = ind;
}
function get_row_index(){
return row_index;
}
jQuery(document).ready(function(){
jQuery('tr input.select_media_library').off().on('click', function( event ){
event.preventDefault();
var index = jQuery(this).closest('tr').index();
**set_row_index(index);**
.
.
.
file_frame.on( 'select', function() {
attachment = file_frame.state().get('selection').first().toJSON();
**index = get_row_index();**
var id = "img_src_" + index;
jQuery('#' + id).attr('value',attachment.url);
});
file_frame.open();
});

How do i actually populate a multiple select box with php returned query, adding into multi dimensional array of jquery?

Sorry for my bad English as I'm not native English speaker.
The question is this,
I have plan to do a three multiple select box in a single page, how to retrieve the query data before hand when the query in php is executed, individual query loop result will be add into a multidimensional array.
2nd, when the user click on any one of the option on the 1st multiple select box, it will structure the 2nd select box accordingly to the by calling out reference from array, how do i work on this?
Lastly, I would like to do this without using ajax.
Here's part of my code,
Javascript/jquery + php
$(document).ready(function(){
var selectValues = { "1" : "General Health",
"2": "Head and Neck",
"3": "Ear, nose and throat" ,
"4": "Stomach, bowel and bladder",
"5": "Bones and muscles",
"6": "Mental Health or confusion",
"7": "Pregnancy Problem",
"8": "Accident, wound or injury"
};
var $cateSymptom = $('#cateSymptom');
var $dropdownSymptom = $("#dropdownSymptom");
$.each(selectValues, function(key, value) {
$('#cateSymptom')
.append($("<option></option>")
.attr("value",key)
.text(value));
});
<?php
$query = "select a.*, asy.*, s.* from ailment as a join symptom_ailment as asy on a.ailment_id = asy.ailment_id join symptom as s on asy.symptom_id = s.symptom_id";
$result = mysqli_query($conn,$query) or die(mysqli_error($conn));
while($row = mysqli_fetch_assoc($result))
{
$sid = $row["symptom_id"];
$sname = $row["symptom_name"];
$stype = $row["stype_id"];
$aname = $row["ailment_name"];
$aid = $row["ailment_id"];
echo "<script>alert('$sid $sname $stype $aname $aid'); </script>";
?>
var selectValues2 = { "<?php echo $stype; ?>" :
{
"<?php echo $sname ?>" :
[
"<?php echo $aid ?>",
"<?php echo $aname; ?>"
]
}
};
<?php }
?>
$cateSymptom.change(function() {
alert('1');
$dropdownSymptom.empty().append(function() {
alert('2');
var output = '';
console.debug(selectValues2);
$.each(selectValues2[$cateSymptom.val()], function(key, value) {
alert('3');
output += '<option>' + key + '</option>';
});
return output;
});
}).change();
});
HTML:
<div id="scCategory">
<h3>Choose Symptoms Category</h3>
<form name="frmSC2" method="POST" id="frmSC2">
<select multiple name="symp[]" id="cateSymptom" style="width:230px;height:280px;">
</select>
</div>
<div id="scDepth">
<h3>List of Symptoms</h3>
<select multiple name="symptom[]" id="dropdownSymptom" style="width:230px;height:280px;">
</select>
</div>
<div id="scCondition">
<h3>Possible Condition</h3>
<select multiple name="condition[]" id="dropdownCondition" style="width:230px;height:240px;">
</select>
</div>
Following is a fully integrated solution for all 3 levels
Data structure uses objects with ID as keys, and a children property if applicable
var data = {
"1": {
"val": "1",
"text": "General Health",
"children": {
"1.0": {
"text": "Item - 1.0",
"val": "1.0",
"children": {
"1.0.0": {
"text": "Item - 1.0.0",
"val": "1.0.0"
}
}
}
}
In the JS the active data for each select is storedd on the element using jQuery data() for easy access to populate the next select within change handler
/* change handler to manage emptying and populating chained selects */
var $selects = $('select').change(function () {
var idx = $selects.index(this),
$currSelect = $(this),
val = $currSelect.val(),
$nextSelect = $selects.eq(idx + 1);
if (idx < 2) {
/* empty select(s) after this one */
$selects.filter(':gt(' + idx + ')').empty();
/* if value update next select */
if (val) {
var nextSelectData = $currSelect.data('selectData')[val].children;
populateSelect($nextSelect, nextSelectData);
}
}
});
/* load first select */
populateSelect($selects.first(), data);
function populateSelect($select, selectData) {
$select.append('<option value=""> -- Select -- </option>')
$.each(selectData, function (key, item) {
$select.append($("<option></option>")
.attr("value", key)
.text(item.text));
});
/* store the data on this element for easy access in change handler */
$select.data('selectData', selectData);
}
DEMO
Since you don't want to use ajax.. The VERY DIRTY way to do this would be to output the PHP array on the page as something like an unordered list (and display:none; or jquery.hide) on those said lists. Point at them with Jquery like so:
var list1 = [];
$('classListOne.li').each(function(i, elem) {
list1.push($(elem).text());
});
Then at that point since you need the next drop down's to reflect what a user implemented on the first drop down. Your going to need to create a pretty hariy IF/else and or CASE statement in Jquery. Once you find the array you need create a another drop-down and append it to where you need it to go like so:
var data = {
'foo': 'bar',
'foo2': 'baz'
}
var s = $('<select />');
for(var val in data) {
$('<option />', {value: val, text: data[val]}).appendTo(s);
}
s.appendTo('body');
This again is a horrible why to do this, but I understand sometimes you can't always use the best technologies. Let me know if that helps at all.

Right Click Jquery Menu don't work after a function rewrite the table

I'm developing a simple example of Right Click Menu using Jquery. I'm using JQuery ContextMenu. So I have a simple table and the jsp code generete the cells in this way:
<div id="catS" class="pure-u-1-3">
<h4 class="l-box">Categorie</h4>
<table class="pure-table pure-table-horizontal l-box" id="catAssociate">
<tbody>
<%ObjectifyService.register(Categoria.class);
List<Key<Categoria>> lCategorie=s.getCategorie();
if(lCategorie!=null){
for(Key<Categoria> k : lCategorie){
Categoria c= ofy().load().now(k);
if(c!=null)
%><tr id="<%out.println(c.getId());%>" ><td id=" <%out.println(c.getId());%>" onclick="getSottocategorieDaC(this); getDispenseDaC(this)"><%out.println(c.getNome());%></td></tr> <%
}
}else{
%><tr><td>Nessuna categoria associata</td></tr><%
}
%>
</tbody>
</table>
</div>
So in an other table i can add elements on the datastore and via the ajax post i update the "catAsscoiate" table. these are my function:
This add the item on the datastore and redraw my table.
function AddAction(t, a) {
$.ajax({
url : 'studenteServlet?action=aggiungiC&ids='+$.urlParam('id')+'&idc='+t.id,
type : "POST",
async : false,
success : function(data) {
console.log(data);
$('#catAssociate tbody > tr').remove();
var html = '';
for(var i = 0; i < data.length; i++)
html += '<tr id='+data[i].id +'><td id='+data[i].id +' onclick="getSottocategorieDaC(this); getDispenseDaC(this)">' + data[i].nome + '</td></tr>';
$('#catAssociate').append(html);
}
});
}
Before the add action the context menu works on catAssociate, after no. this is the code:
$(document).ready(function() {
$('#catAssociate tbody tr').contextMenu('myMenu2', {
bindings: {
'open': function(t) { DeleteAction(t, "Open"); },
}
...
Can anyone explain me why?
Thanks!
when you replace all the html using $('#catAssociate').append(html); you effectively remove / lose all the event bindings that where attached to the old content that you just zapped.
so just reapply them after you rebuild the DOM in your success function:
$('#catAssociate').append(html);
$('#catAssociate tbody tr').contextMenu('myMenu2', {
bindings: {
'open': function(t) { DeleteAction(t, "Open"); },
}

Categories