i interested in learn how to correctly add .bind code to object, then he changed. This object is not unic and have class selector insted of id, but it have a <div> wrapper:
<div id="GDI">
<table class = "Tiberium">
...
<tbody>
<tr>...</tr>
...
<tr>...</tr>
</tbody>
</table>
</div>
<div id="NOD">
<table class = "Tiberium">
...
<tbody>
<tr>...</tr>
...
<tr>...</tr>
</tbody>
</table>
</div>
The data changed in table with class "Tiberium" in <tbody> space (e.g. was added new row), i need simple alert then data changed in GDI table, but dont know how to do it.
Code that i tried:
$('.Tiberium').bind('DOMSubtreeModified', Alert);
Where Alert is function.
This code capture changes in both tables, and i got alerts then one of them changed. So how i can track changes only in "Tiberium" table in GDI space?
p.s. i'v tried $('#NOD').bind('DOMSubtreeModified', Alert);
but this code alert me 3 times in row, and it possible run every code in function 3 times. (i think it happend in case of this hierarchy).
The DOMSubTreeModified event is deprecated. A better alternative to this solution is to use the MutationObserver.
var toBeObserved = document.getElementsByClassName('Tiberium');
if('MutationObserver' in window) { // ensure browser support
var observer = new MutationObserver(myEventHandler); // instantiate
observer.observe(toBeObserved, { // start observing
childList : true,
subtree : true
});
}
Everytime the toBeObserved element is mutated, the myEventHandler function will be called. You can add your custom code within this function.
Could you please try following code:
$('.Tiberium').bind('DOMSubtreeModified', function(){
//check the parent div's id
if($(this).parent().attr("id") == "GDI")
Alert //your alert function call
});
Related
I have the following Dojo Javascript snippet:
postCreate: function () {
this.inherited(arguments);
var hitchWidgetToaddLevelButtonClickHandler = DojoBaseLang.hitch(this, addLevelButtonClickHandler);
DojoOn(this.AddLevelButton, "click", hitchWidgetToaddLevelButtonClickHandler);
function addLevelButtonClickHandler() {
hierarchyLevelNumber += 1;
var myButton = new Button({
label: "Click me!",
id: "level_button_" + hierarchyLevelNumber,
onClick: function(){
// Do something:
console.log("Hello there, ");
}
}).placeAt(someNode,"last").startup();
var registeredRemovalButton = DijitRegistry.byId(("level_button_" + hierarchyLevelNumber));
DojoOn(registeredRemovalButton, "click", function someFunction() {
console.log("how are you?");
});
}
}
and the following HTML
<div id="settingsBorderContainer" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline', gutters:false, region:'top'" class="${theme}">
<table data-dojo-attach-point="HierarchyLevelsTable">
<tr>
<th>Level</th>
<th> Table Name </th>
<th> Column Name</th>
</tr>
<td id="someNode">
</td>
</table>
</div>
The goal here is, when AddLevelButton is clicked it dynamically creates a row in the table with the necessary information and a new button for each row. Note that the HTML and Javascript are largely simplified to illustrate my problem. I did not include all of the row logic that occurs in addLevelButtonClickHandler() method. The HTMl is built as intended, as you can see in the following screenshot:
The problem is that everytime I add a button, only the last button's event listeners work, i.e. in the case of the screenshot the button circled in red logs: Hello there, you called the remove handler [object MouseEvent], and the previous button in the table no longer can be clicked and catch the necessary event. Sorry if the code is a gross-simplification of my goal, I appreciate any help that is offered.
*********EDIT**************
So I took a different approach and placed only 1 button total, and delete level by level from the bottom up. As long as it resides outside of a <table> it functions..Which brings me to the conclusion of NEVER PUT DIJITS OR BUTTONS IN A TABLE After many hours lost, I would recommend if you absolutely need a table in the first place, just placing the button next to the table as necessary using CSS and floats
I will leave this question as unanswered until someone may be able to offer an explanation of why the inner table approach does not work.
While working with dojo. You should never use node.innerHTML to add or update nodes. It will basically convert all the dijits into HTML string and parse as regular HTML by the browser. which in turn will destroy dom object and event associated to it.
Instead create dom object using dojo/dom-construct and add it with appendChild for DOM nodes or addChild in case of container dijits.
I'm new to Vue. I can not remove an item from a DOM, in Vue.js Javascript file.
I successfully managed to make an ajax post request, which removes a specific record from my database.
Once it's removed, I need to remove it from a DOM, so it won't shop up without need to reload the same page - I guess you know what I mean.
I can do it in jQuery, but I wonder how it should be done in Vue.js actually ?
Here is my portion of the code:
// SOME CODE BEFORE ...
onSubmit: function(e){
e.preventDefault();
$tablerow = this.el.parentNode.parentNode;
// Assign a correct submit request type and url
this.vm
.$http[this.getRequestType()](this.el.action)
.then(this.onComplete.bind(this))
.catch(this.onError.bind(this))
;
},
onComplete: function(){
// Remove the item from a DOM <<< I NEED TO REMOVE PARENT <tr/> ELEMENT
$(this.el).closest('tr').fadeOut(300, function(){
this.remove();
});
// If complete message exists, use it as a feedback
if(this.params.complete){
alert(this.params.complete);
}
},
// SOME CODE AFTER ...
Any suggestion please ? Sorry if my question is dumb, but I have not best knowledge in programming.
Normally you will have a list of items you are displaying with v-for in your table rows which are stored in an array. After your ajax call you can remove this item using this.items.$remove(item) and it will be automatically removed from where it is displayed in the DOM.
Since you didn't show your template I will try to recreate a similar scenario of what i think you are trying to do
data: function(){
return {
items: ['item1','item2','item3']
}
},
methods: {
remove: function(item){
ajaxCall.then(function(){
this.items.$remove(item);//will remove the <tr> from the DOM
});
}
}
Your template can be like
<tbody>
<tr v-for="item in items" v-on:click="remove(item)">{{ item }}</tr>
</tbody>
I need to make a data table for an enyo project I am working on that will ultimately display the result of an Ajax call.
This (Blatantly stolen from ryanjduffy here)seems to be a good starting point, but when I try to call setData() from a button event (rather than in the constructor) as I have here I get the following error:
InvalidCharacterError: String contains an invalid character # http://enyojs.com/enyo-2.1/enyo/source/dom/Control.js:681
I looked at the Control.js code and it seems that it tries to create a new node, but the this.tag property is set to null and things break.
I feel like I am missing something really simple, but I just can't see the problem yet...
Can someone tell me what I am doing wrong?
Thanks!
EDIT 1:
Apparently calling render() is not needed. Here is the original working version with render() commented out. Everything looks great. However, if I try to remove render() from the version that requires a button click, the repeater starts creating div's above the table instead of tr td's inside the table...
EDIT 2:
Basically, from what I can tell, the Repeater inside of a table will lose it's parent once the table is rendered (or something like that). The result is the Repeater will start rendering its new items outside of the original table and because a td tag without a table makes no sense, it just renders a div.
The solution I have come up with is to give the Repeater itself a table tag so its children always wind up in the right spot. This adds the challenge of needing to recreate the header line each time, but it is not that big of a deal. I have a working example if anyone is interested.
I'm sure you're not looking for a solution any longer but since I was mentioned in the post, I thought I'd let you know what I figured out. In short, my code shouldn't have worked but since browsers are forgiving, it did ... sort of.
When the code run at create time, it renders something like this:
<table>
<tr> <!-- header row --> </tr>
<div> <!-- repeater tag -->
<tr> <!-- repeater row --> </tr>
</div>
</table>
The browser looks at that and says, "Hey, dummy! No <div>s in a <table>" and kicks it out but leaves the <tr>s.
In your example, since you're delaying the render of the rows, Enyo renders:
<table>
<tr> <!-- header row --> </tr>
<div></div>
</table>
And the browser ejects the <div> and you're left with an empty table. When you later set the data, those rows are rendered into the div. Unfortunately, since you're rendering <tr> and <td>, those aren't valid outside a table so you just get text.
I found a couple solutions. The simplest was to set the tag of the Repeater to be TBODY which is allowed inside a table. The slightly more involved solution was to make the DataTable inherit from Repeater and set the header row to be chrome so they're not removed when updating the data.
Option #2 Fiddle
enyo.kind({
name:"DataTable",
tag: "table",
kind: "Repeater",
published:{
map:0,
data:0
},
handlers: {
onSetupItem: "setupItem"
},
components:[
{name:"row", kind:"DataRow"}
],
create:function() {
this.inherited(arguments);
this.mapChanged = this.dataChanged = enyo.bind(this, "refresh");
this.refresh();
},
refresh:function() {
if(this.map && this.data) {
this.buildHeader();
this.setCount(this.data.length);
}
},
buildHeader:function() {
if(this.$.header) {
this.$.header.destroyClientControls();
} else {
this.createComponent({name:"header", tag:"tr", isChrome: true});
}
for(var i=0;i<this.map.length;i++) {
this.$.header.createComponent({content:this.map[i].header, tag:"th"});
}
this.$.header.render();
},
setupItem:function(source, event) {
for(var i=0;i<this.map.length;i++) {
event.item.$.row.createComponent({content:this.data[event.index][this.map[i].field]});
}
event.item.render();
return true;
}
});
I am not so good with jQuery and I need your help. First, let me explain the situation. I have an HTML table like this :
<table id="table">
<tr><td><img class="image" />test</td><td></td></tr>
<tr><td><img class="image" />test</td><td></td></tr>
</table>
What I need to do is to get the full content of the table : $("#table").html() but without the img tags. (But I do not want to delete them in the original content, only in the "copied" content)
I tried something like that :
$('#table').clone().find('.image').remove().parent().parent().html()
But it is undefined (I guess as the element is removed, I cannot access it and get the parent).
How would you do it ?
Thanks
EDIT: To try to explain it better, the result I would need is :
<table id="table">
<tr><td>test</td><td></td></tr>
<tr><td>test</td><td></td></tr>
</table>
$('#report').clone().find('.plusImage').remove().html() will not return the table's content.
// First clone table and save it to a new variable
var clonedTable = $('#table').clone();
// remove all img tags
clonedTable.find('img').remove();
// test it
console.log(clonedTable.html());
You can also use a regular expression to remove it from the string without cloning DOM:
var contentWithoutImg = $('#table').html().replace(/<img[^>]+\>/ig, '');
console.log(contentWithoutImg);
You can't chain a method for your table to remove() because it returns the element that is removed. Hast has posted the proper answer, but if you think you'll need this more than just once and wanted to create your own method to remove children and return the container, you can use the following:
$.fn.removeDesc = function(sel){
return this.each(function(){
$(this).find(sel).remove();
});
}
You could then use it like so:
var tableHTML = $('#report').clone().removeDesc('.plusImage').html();
JSFiddle
i'm using 2 dropdowns where the second gets populated from the first choice.
My problem is that i'm not getting the value from the first dropdown.
What i get is [object Object].
Here's the javascript and php code:
Thanks.
Javascript:
function getState(){
$("#selectestate").bind("change",function(){
$("#selectcity").load("results/ajaxcity", {stat: $(this).val()} ); //This is where the problem is
alert({stat: $(this).val()});//Shows [object Object]
});
return false;
}
PHP:
$curstat=$this -> input -> post('state'); //current selected state in first dropdown
<tr>
<?php $js = 'id="selectstate" onChange="getState();"';?>
<td><h3> State: </h3></td>
<td id="selectestate"><?php echo form_dropdown('state', $stat, $curstat, $js);?></td>
</tr>
<tr>
<td><h3> City: </h3></td>
<td id="selectcity"><?php echo form_dropdown('city', $cit);?></td>
</tr>
You need to alter this code:
$("#selectestate").bind("change",function(){
to this:
$("#selectestate select").bind("change",function(){
You are asking for the value of the <td id="selectstate"> ... which is of course null. #selectstate select loads the actual <select> element that you are looking for, which will then enable you to get its value.
You will also want to change $("#selectcity") to $("#selectcity select") to avoid the same problem in your anonymous function.
Finally, your alert is behaving as expected. {} defines an object in Javascript. So you are alerting an object containing a single attribute. Just alert($(this).val());// Should show the value
If it still fails it's because either:
A) Your URL is wrong
or
B) There is something wrong with the php function called by results/ajaxcity
EDIT:
Smacks head: I should have caught this. In your code you have this function:
1. function getState(){
2. $("#selectestate select").bind("change",function(){
3.
4. $("#selectcity select").load("results/ajaxcity", {stat: $(this).val()} );
5. alert($(this).val());
6. });
7. return false;
8. }
Your generated HTML looks something like this:
<select name="state" id="selectstate" onChange="getState();">
THE PROBLEM: When you use the <select> for the first time your function is called and jQuery binds an anonymous function to the change event for select (line #2) that will be executed every time the change event fires from this select from now on. Every time you select the dropdown a new anonymous function is bound by line #2 and all of the functions that are currently bound to the dropdown are executed. (So if you use the dropdown N times the "change" function will fire N-1 times.)
THE SOLUTION: Use $(document).ready() to bind your function. Your restructured code will look like this:
<script type="text/javascript">
function getState(element){
$("#selectcity select").load("results/ajaxcity", {stat: $(element).val()} );
alert($(element).val());
return false;
}
</script>
//... snip ...
<?php $js = 'id="selectstate"';?>
//... snip ...
<script type="text/javascript">
$(document).ready(function() {
$("#selectestate select").bind("change", getState);
});
</script>
There is no value for td element, which you are accessing in "#selectestate" selector. Instead of {stat: $(this).val()} you should find inner select element {stat: $(this).find("select").val()}
You're loading the .val() of a <td> element ($(this), inside your handler for a TD). You need to get the id of the <select> tag.
If you really can't find the ID (or codeigniter doesn't set it.. impossible to tell from your example since form_dropdown() is creating it), then instead of $(this).val() you could try $('select',this).val() which will find the value of the first <select> tag within the TD.
Also in your debugging, {stat: $(this).val()} is an object, so of course that's what alert() shows you. Try using firebug, and then change alert() to console.log() -- the firebug console will show you the full object. You could also simply do alert($(this).val()) -- though realize of course that it will be wrong due to the first paragraph above.