I'll try to keep it at simple as I can.
I have a JSON object that is pulled via AJAX. I am displaying a list of icons in a main div from the data dynamically which can be toggled on or off.
I have a secondary div where the selected items are appearing, while the main div icon receives a class of active.
I want the end user to be able to remove any of them by clicking on them on either the main div or secondary div.
Most of this is working, but I'm having trouble figuring out the best way to map them together so that I have 2 separate click events which can control the same outcome.
I think it may have something to do with the fact that I'm dynamically creating elements... which create more elements... which have to alter the initial elements.
My structure so far is to map the current selection inside of an array. This gives me control over keeping a code-based list of everything that is selected (there is much more data than in the example I'll be providing).
So, here is how I have it so far:
HTML:
<div id="options"></div>
<div id="selectedOptions"></div>
Javascript/jQuery:
// Simple simulated AJAX data
var ourData = {
"color1": "yellow",
"color2": "blue"
};
var $options = $('#options');
var $selectedOptions = $('#selectedOptions');
// Array to keep track of which objects are selected
var selectedOptions = [];
// Makes the initial option dynamic list
makeOptions(ourData, $options);
// If an option from the main div is clicked, handle class changing
$('button').on('click', function(){
pickOption($(this));
});
/* This function is the problem. The option gets removed from the array, and from the secondary div, but the class of active still occurs on the main div. */
$selectedOptions.on('click', '.optionActive', function(){
var option = $(this).data('color');
var optionPosition = jQuery.inArray(option, selectedOptions);
selectedOptions.splice(optionPosition, 1);
displayOptions(selectedOptions, $selectedOptions);
});
// Creates initial icons (buttons in this case) to the DOM and applies a data-attribute for the color
function makeOptions(options, $container){
var $results = $('<div id="results">');
$.each(options, function(key, value){
var $optionButton = $('<button>' + key + ':' + value + '</button>');
$optionButton.data('color', value);
$results.append($optionButton);
});
$container.append($results);
}
/* Handler for selecting an option from the Main Div. Handling the class active.
I am not using a simple classToggle because there are many situations where a click is not allowed */
function pickOption($option){
var selectedOption = $option.data('color');
// If the option returns true, or that it doesn't exist yet
if(modifyOptions(selectedOption, selectedOptions)){
$option.addClass('active');
} else {
$option.removeClass('active');
}
// Recreate our current selected options
displayOptions(selectedOptions, $selectedOptions);
}
/* Searches array to see if the option exists. Returns true or false and either pushes or splices the option from the array */
function modifyOptions(option){
var optionPosition = jQuery.inArray(option, selectedOptions);
if(optionPosition == -1){
selectedOptions.push(option);
return true;
} else {
selectedOptions.splice(optionPosition, 1);
return false;
}
}
/* Displays all currently selected options that exist in our array */
function displayOptions(selectedOptions, $container){
$container.empty();
$.each(selectedOptions, function(option, value){
var $optionTile = $('<div class="optionActive">');
$optionTile.data('color', value)
.text(option + ":" + value)
.css('background', value);
$container.append($optionTile);
});
}
So, to summarize, I want some some way to remove the .active class from the main div equivalent element when the item from the second div is clicked.
I tried removing the class active by searching for any elements with the data-color=data-color of the selected item, but I couldn't get that to work.
ex:
$('*[data-color="' + $(this).data('color') + '"]').removeClass('active');
I would really like some data approach to this, such as removing the class active if it had data-color="yellow" for instance.
Playground:
https://jsfiddle.net/c75xcLha/
EDIT:
Both Are Selected, working as designed:
Clicked Yellow Div. Yellow Button is still active:
Should remove the active class from the button when the yellow div OR the button is pressed, as shown here:
You are assigning data-* property using .data(PROP), not attribute hence element having data-* property could not be accessed/selected using attribute-selector, assign attribute using .attr('data-color') instead of .data(property)
Attribute Equals Selector [name=”value”], Selects elements that have the specified attribute with a value exactly equal to a certain value.
.data( key, value ), Store arbitrary data associated with the matched elements.
When you use .data() to update a data value, it is updating internal object managed by jQuery, so it will not be updated in the data-* attribute[Ref]
// Simple simulated AJAX data
var ourData = {
"color1": "yellow",
"color2": "blue"
};
var $options = $('#options');
var $selectedOptions = $('#selectedOptions');
// Array to keep track of which objects are selected
var selectedOptions = [];
// Makes the initial option dynamic list
makeOptions(ourData, $options);
// If an option from the main div is clicked, handle class changing
$('button').on('click', function() {
pickOption($(this));
});
/* This function is the problem. The option gets removed from the array, and from the secondary div, but the class of active still occurs on the main div. */
$selectedOptions.on('click', '.optionActive', function() {
var option = $(this).data('color');
var optionPosition = jQuery.inArray(option, selectedOptions);
selectedOptions.splice(optionPosition, 1);
$('[data-color="' + $(this).data('color') + '"]').removeClass('active');
displayOptions(selectedOptions, $selectedOptions);
});
// Creates initial icons (buttons in this case) to the DOM and applies a data-attribute for the color
function makeOptions(options, $container) {
var $results = $('<div id="results">');
$.each(options, function(key, value) {
var $optionButton = $('<button>' + key + ':' + value + '</button>');
$optionButton.attr('data-color', value);
//___________^^^^^^^^^^^^^^^^^^Little trick here!
$results.append($optionButton);
});
$container.append($results);
}
/* Handler for selecting an option from the Main Div. Handling the class active.
I am not using a simple classToggle because there are many situations where a click is not allowed */
function pickOption($option) {
var selectedOption = $option.data('color');
// If the option returns true, or that it doesn't exist yet
if (modifyOptions(selectedOption, selectedOptions)) {
$option.addClass('active');
} else {
$option.removeClass('active');
}
// Recreate our current selected options
displayOptions(selectedOptions, $selectedOptions);
}
/* Searches array to see if the option exists. Returns true or false and either pushes or splices the option from the array */
function modifyOptions(option) {
var optionPosition = jQuery.inArray(option, selectedOptions);
if (optionPosition == -1) {
selectedOptions.push(option);
return true;
} else {
selectedOptions.splice(optionPosition, 1);
return false;
}
}
/* Displays all currently selected options that exist in our array */
function displayOptions(selectedOptions, $container) {
$container.empty();
$.each(selectedOptions, function(option, value) {
var $optionTile = $('<div class="optionActive">');
$optionTile.data('color', value)
.text(option + ":" + value)
.css('background', value);
$container.append($optionTile);
});
}
.active {
background: #CCF;
}
.optionActive {
min-width: 100px;
min-height: 100px;
display: inline-block;
margin: 1em;
background: #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="options"></div>
<div id="selectedOptions"></div>
Updated Fiddle
Edit: If you still want to stick with .data method, use .filter to select target element.
$('button').filter(function(){
return $(this).data('color')=='yellow';
}).removeClass('active');
I have a table that displays selectable information. Sometimes there are child rows that are selectable.
I want the parent rows to be selectable if they have no children, otherwise only the child rows should be selectable. This is a select-only-one type of table.
This table works as expected. However, I want to disable the hover on the non-selectable parent row.
Here is a working plunker: http://plnkr.co/edit/Z0cgHKx2qxpekEE36O1K?p=preview
Here is an example of some of the code in the controller:
scope.parentSelected = [];
$scope.childSelected = [];
$scope.getParentDetails = function(parentObj) {
if(!parentObj.jobs || parentObj.jobs.length === 0) {
nonSelectOtherRows();
var index = $scope.pro.indexOf(parentObj);
$scope.parentSelected[index] = !$scope.parentSelected[index];
// get details for parent row using parentObj
console.log(parentObj);
}
};
$scope.getChildDetails = function(parentObj, childObj) {
nonSelectOtherRows();
var parentIndex = $scope.pro.indexOf(parentObj);
var childIndex = parentObj.jobs.indexOf(childObj);
$scope.childSelected[parentIndex] = [];
$scope.childSelected[parentIndex][childIndex] = !$scope.childSelected[parentIndex][childIndex];
// get details for parent and child rows using parentObj and childObj.
// childObj is the childRow selected
console.log(parentObj);
console.log(childObj);
}
Remove table-hover attribute.
Implement your ng-mouseover and ng-mouseleave functions.
$scope.hoverIn = function(row){
row.hoverEdit = true;//check selectable or not
};
$scope.hoverOut = function(row){
row.hoverEdit = false;
};
Define css class for hover.
.custom-hover {
background-color: red;
}
Finally add class to your tr
`'custom-hover': x.hoverEdit`
here is: http://plnkr.co/edit/CJxi86GyM8jMbtehPQgU?p=preview
Add your selectable control inside hoverIn and it will be work.
try to use ng-class. it will help you.
I'm producing buttons for editing and removing each element in a Firebase database dynamically with javascript. And when there is only one element in the database (these elements represent polls/elections), the below code works fine. But when there is more than one database element, and hence more than one row of buttons, only the final pair of edit/remove buttons added are actually bound with the click event, which I suppose means all previous bindings are being overwritten in some way? I should also mention that both pollsRef.once() and pollsSnapshot.forEach() are asynchronous function calls (as are all Firebase API calls). Here is the function which creates and binds the buttons. ...
function displayCurrentPollsForEditing(pollsRef)
{
var tbl = createTable();
var th = ('<th>Polls</th>');
$(th).attr('colspan', '3');
$(th).appendTo($(tbl).children('thead'));
pollsRef.once('value', function(pollsSnapshot) {
pollsSnapshot.forEach(function(pollsChild) {
var type = pollsChild.name();
// If this is true if means we have a poll node
if ($.trim(type) !== "NumPolls")
{
// Create variables
var pollRef = pollsRef.child(type);
var pollName = pollsChild.val().Name;
var btnEditPoll = $('<button>EDIT</button>');
var btnRemovePoll = $('<button>REMOVE</button>');
var tr = $('<tr></tr>');
var voterColumn = $('<td></td>');
var editColumn = $('<td></td>');
var rmvColumn = $('<td></td>');
// Append text and set attributes and listeners
$(voterColumn).text(pollName);
$(voterColumn).attr('width', '300px');
$(btnEditPoll).attr({
'class': 'formee-table-button',
'font-size': '1.0em'
});
$(btnRemovePoll).attr({
'class': 'formee-table-remove-button',
'font-size': '1.0em'
});
$(btnEditPoll).appendTo($(editColumn));
$(btnRemovePoll).appendTo($(rmvColumn));
// Append to row and row to table body
$(tr).append(voterColumn).append(editColumn).append(rmvColumn);
$(tr).appendTo($(tbl).children('tbody'));
// Append table to div to be displayed
$('div#divEditPoll fieldset#selectPoll div#appendPolls').empty();
$(tbl).appendTo('div#divEditPoll fieldset#selectPoll div#appendPolls');
$(btnEditPoll).click(function() {
displayPollEditOptions(pollRef);
return false;
});
$(btnRemovePoll).click(function() {
deletePoll($(this), pollsRef);
return false;
});
}
});
});
}
The buttons are just rendered in a programmatically generated table, all the jQuery selectors are correct.
So, i have span element where i appending some content - sometimes this content is duplicated. How to remove this one value which is duplicate of another ...
This is how looks like my output html:
<span class="some_class">
"value01"
"value01"
"value02"
"value03"
"value03"
</span>
I can't add any function because i have no idea how to do this, can u help me?
If these values are being added by JS code, then You can make sth like this:
http://jsfiddle.net/Sahadar/Nzs52/5/
You just have to make object which will store all strings placed inside this span, then just before insertion check if this inserted string is already in store object.
function(event) {
var textareaValue = textarea.value();
if(insertedTexts[textareaValue]) {
event.preventDefault();
textarea.value('');
} else {
insertedTexts[textareaValue] = true;
someSpan.append("\""+textareaValue+"\"");
}
}
If these values are already inside span, use function as follows:
var someSpan = $('.some_class');
var insertedTexts = [];
var result = someSpan.text().match(/"\w+(?=\")/gm);
result = result.map(function(value) {
return value.substring(1,value.length);
});
result.forEach(function(value) {
if(insertedTexts.indexOf(value) === -1) {
insertedTexts.push(value);
}
});
var newSpanText = "\""+insertedTexts.join('""')+"\"";
someSpan.text(newSpanText);
console.info(result, insertedTexts);
It's rebuilding span text (trimming etc.) but main functinality is preserved.
jsFiddle working copy:
http://jsfiddle.net/Sahadar/kKNXG/6/
Create an array variable
var vals = [];
which keeps track of the items. Then, in your function that appends items to the span check:
if (vals.indexOf("Mynewvalue") > -1) {
// Add to the span...
}
I'm using this: http://docs.jquery.com/UI/Autocomplete
I'm initializing a text box like this (partial code):
$('#foo').autocomplete
{
source: function()
{
// How to get the id of the element?
}
}
In the source callback, I need to know what the id is of the current element. In this example, it's obviously foo; in the real application, the selector is dynamically assigned so I don't know what the id is.
I looked at the following:
console.debug($(this)); // displays [a.widget.a]
console.debug($(this.id)); // displays []
console.debug($(this).attr('id')); // displays undefined
How to get the id of the element?
Rather than assigning variables names to all the inputs you want autocomplete on, you can use:
$('#some_id').autocomplete {
source: function() {
var element = this.element[0];
var element_id = this.element[0].id;
}
}
You could just use...
var element = $('#one');
element.autocomplete
{
source: function()
{
var id = element.id;
}
}