Function does not work properly if not nested in another function - javascript

Sorry for unclear title but I couldn't find anything that could suit my problem.To better explain what it is let me show you my javascript code:
function askForIDForCommand()
{
var content;
$.post("Somepage.aspx", function (data)
{
content = $(data).find("#myDiv").html();
});
var myFunc = function () { }
var buttons = [{ text: 'OK', click: myFunc}];
ui_window("Hi", 630, content, buttons);
}
As you can see I declare a variable called content. Then I assign the html of a specified div to it. And then I send it to ui_window function which just displays a jquery dialog with the specified content. The problem is I don't get that html content in the dialog. When I look up the value of "content" with Firebug I can see that it contains html content. What makes me desperate is if I change the above function to the below one the html content gets displayed in the dialog:
function askForIDForCommand()
{
var content;
$.post("Somepage.aspx", function (data)
{
content = $(data).find("#myDiv").html();
var myFunc = function () { }
var buttons = [{ text: 'OK', click: myFunc}];
ui_window("Hi", 630, content, buttons);
});
}
In case you can't notice the difference, I just put the call of ui_window inside the $.post() method. And it works. Why's that?
And here's the html content in case you need it:
<table>
<tr>
<td align="right">
<label>
Enter the ID:</label>
</td>
<td>
<input id="txtID" type="text" onkeydown="return onlyNumbers(event);" maxlength="8"/>
</td>
</tr>
</table>

You're not assigning to content before you call ui_window. That assignment happens inside your anomyous function and therefore is not executed until someone calls that function (that is, once the post to Somepage.aspx is completed).
In contrast, you're calling ui_window() as soon as you have started the post to Somepage, but without waiting for that operation to finish. At that time your completion function still hasn't been called, and therefore content still contains undefined.

The problem is that the inner function is called when you recieve response from server. Then in the first case the variable is not assigned yet when those lines are executed and in the second one you are sure that ui_window is called with available data.

The problem is the AJAX call to the server. In the first case, you send a request and go straight to the next command, ie myFunc and so. Therefore your content variable isn't initialized at this moment.

Related

jQuery.trigger() not firing on refresh

I have an html page, Home.htm, that contains an iframe which holds another page Child.htm, i.e.
<body>
<div>
<iframe id="child-iframe" src="Child.htm"></iframe>
</div>
</body>
Home.htm also contains some javascript/jQuery that retrieves data and depending on this data retrieves more information and then triggers an event set up in the Child.htm file to display this information within Child.htm, i.e.
<script>
$(document).ready(function () {
$.getJSON("http://getsummarydata/001")
.done(function (data) {
if (data meets some condition) {
$.getJSON("http://getspecificdata/001")
.done(function (data) {
// Trigger the event
var target = $("#child-iframe");
if (target[0] !== undefined) {
target[0].contentWindow.$(target[0].contentWindow.document).trigger("data-available", [data]);
}
});
}
}
});
</script>
Within Child.htm I have set up the custom event, data-available, and its handler using jQuery as follows;
<script>
// Event handler
function myFunc(data) {
// Display the data
}
// Event
$(document).on('data-available', function (__e, __data) {
myFunc(__data);
});
</script>
When the Home.htm page is first loaded the data is retrieved succesfully, the event is triggered and the data is displayed as expected within the iframe. However, when I refresh the Home.htm (F5), the data is still retreived but the trigger is no longer fired - infact I get the following error.
Uncaught TypeError: target[0].contentWindow.$ is not a function
Even though target[0].contentWindow seems ok.
I don't know why this happening on a refresh and any help with resolving this would be much appreciated.
Paul
It sounds like your events are firing before the iframe has completely loaded. That would explain why it can't find $ when it needs it, but it is there when you inspect it. One potential reason might be that your data requests are cached and so return almost immediately.

Defining a hardcoded Javascript function dynamically

I am programming a web frontend for a database application. I have several function calls in the html body, like:
<input type=button value="Set 1" id="btn1" onClick=edit_entry(this,"edit","title")>
<input type=button value="Set 2" id="btn2" onClick=edit_entry(this,"edit","name")>
<input type=button value="Set 3" id="btn3" onClick=edit_entry(this,"edit","gender")>
function edit_entry(src, action, arg1) {
alert(src.onclick);
src.onclick = function () { edit_entry( src, action, arg1 };
alert(src.onclick);
}
When clicked on "btn1", the first alert returns the hardcoded function definition: function onclick(event) { edit_entry(this,"edit","title") }
But the second alert returns the function definition with variables function onclick(event) { edit_entry(src, action, arg1) }
So when these variables change later the function does get the wrong values. How can I apply the content of the variables to the function definition instead of the variables itself so that the definition is again function onclick(event) { edit_entry(this,"edit","title") } ?
P.S.: I know that this code snippet makes no sense as it shall only describe my problem as simple as possible.
Here is my code I was referring to. I hope this all makes more sense now. Sorry for the inconvenience.
HTML Body:
<input type="button" value="Edit" id="group_1_button_edit" class="action_element" onClick=edit_entries(this,"edit","artnr","artalt","bez1","bez2","bez3")>
<input type="button" value="Edit" id="group_9_button_edit" class="action_element" onClick=edit_entries(this,"edit","dok1","dok2","dok3","dok4","dok5")>
The values behind "edit" are the IDs of the input textboxes the content will be read from.
function edit_entries(caller,action,opt1,opt2,opt3,opt4,opt5,opt6,opt7,opt8,opt9,opt10,opt11,opt12) {
caller_id = caller.id.split("_");
id = caller_id[1];
switch(action) {
case "edit":
//Making textboxes writeable for changing values
//[...]
document.getElementById("group_"+id+"_button_edit").value="Save";
document.getElementById("group_"+id+"_button_edit").onclick=function(){ edit_entries(this,"save",opt1,opt2,opt3,opt4,opt5,opt6,opt7,opt8,opt9,opt10,opt11,opt12); };
break;
case "save":
if (confirm("Datensatz wirklich aktualisieren?")) {
artnr_key = XML_OBJ.getElementsByTagName("artnr")[0].textContent;
string = "";
//Building the AJAX Request String: textbox id = value
url = 'mysql_req_n1.php?type=edit_entries&'+string;
send_request(url);
}
break;
}
}
//called by AJAX handler
function edit_entries_unlock() {
//Getting "id" by value check
counter_a = 1;
while (counter_a <= 9) {
if (document.getElementById("group_"+counter_a+"_button_edit").value == "Save") id = counter_a;
counter_a++;
}
//Getting textbox IDs located in the AJAX response
opts = XML_OBJ.getElementsByTagName("opts")[0].textContent;
options = opts.split(",");
//Making textboxes readonly again
//[...]
document.getElementById("group_"+id+"_button_edit").value="Edit";
document.getElementById("group_"+id+"_button_edit").onclick=function(){ edit_entries(this,"edit",options[0],options[1],options[2],options[3],options[4],options[5],options[6],options[7],options[8],options[9],options[10],options[11]); };
}
And that is what happens:
I click on the first button (group_1_button_edit). It jumps to the switch block "edit" making the textboxes writable and changing the edit button to a save button. Works fine.
I click on save. The switch block "save" builds the request string and starts the ajax request.
The ajax handler starts edit_entries_unlock() when the response is there. Part of the XML Response are the textbox IDs I have used before. The onclick function gets changed again to an "edit" function with the corresponding textbox IDs from the XML object.
Now I click on the second button "group_9_button_edit". Everything is working like mentioned above. No problems. The textboxes of group 9 unlock, get saved und locked again as wanted.
But now the bug: I click on the first button again "group_1_button_edit" which now uses the changed function definition. It starts the switch block "edit" but with the values of the textbox IDs of GROUP 9 (which I edited before) and not GROUP 1.
I guess it has something to do with the variables opt1-opt12. They always contain the values of the last "edit_entries_unlock()" run. And as all the edited function definitions uses opt1-opt12 as well they start with the values of the last run and not with the values I used when recreating the function definition.
For that reason I asked how to build a function definition with the content of variables during the function creation process instead of the content during the execution process.
I hope that makes a lot more sense now. Sorry for the wall of text.
This is a very bad way to pass data.
You should avoid using inline code
<input type=button value="Set 1" id="btn1" onClick=edit_entry(this,"edit","title")>
<input type=button value="Set 2" id="btn2" onClick=edit_entry(this,"edit","name")>
<input type=button value="Set 3" id="btn3" onClick=edit_entry(this,"edit","gender")>
Should be
<input type=button value="Set 1" id="btn1" data-field-name="title">
<input type=button value="Set 2" id="btn2" data-field-name="name">
<input type=button value="Set 3" id="btn3" data-field-name="gender">
<script>
(function(){ // or use on load event
// define the click function
var clickFunction = function(event){
// get the element data
var fieldName = event.target.attributes["data-field-name"].value;
// do what you need to do.....
}
// query the DOM to get the elements you are after.
var el = document.getElementsByTagName("input");
// iterate them and add the event handler to each.
for(var i = 0; i < el.length; i++){
el[i].addEventListener("click",clickFunction,false);
}
})();
</script>
As for what you are trying to do in the example you gave I have no clue so maybe this will help you.
You onclick handler creates a closure. So, the values src, action and arg1 in the below (from your edit_entry function) will be what it was at the time this function was created / recreated (the latter for when you click it the next time)
src.onclick = function () { edit_entry( src, action, arg1 };
You'd be able to modify these only within the same method (or it's child methods). Note that since you set the onclick to the above you are basically passing around the same variables into the handler the next time it is clicked.
Any changes you are seeing for these variables would be from within your onclick handler (and not external to it)
Finally with the help of T.J.Crowder I was able to fix the code.
The line that I needed to fix was
options = opts.split(",");
to
var options = opts.split(",");
I didn't know that declaring variables inside a function without var would make them a part of the window object and therefore making it a global variable. So my closure was accessing a global variable instead a local one.
One small word, but with big impact.

Show HTML objects

I wish to show out other objects when the onclick function is clicked. When i click that button, it will hide one object and show two other objects. I have already set the style.visibility to visible. But the show two object does not works.
Update Sample:
<input type="submit" id="show" name="show" value="show" onclick="RemoveDoc(); document.getElementById('docname').style.visibility='hidden'; document.getElementById('browse').style.visibility='visible'; return false;" />
//browse input
<input type ="file" name="browse" id="browse">
Method 2:
//Using my RemoveDoc() function, I want the button of browse being show out.
function RemoveDoc(Doc)
{
xmlhttp1=new XMLHttpRequest();
xmlhttp1.open("GET","functions/remove.php?Doc="+Doc,true);
xmlhttp1.onreadystatechange=function()
{
if (xmlhttp1.readyState==4 && xmlhttp1.status==200)
{
//when i run debugging, it says that the style of null..
document.getElementById("browse").style.visibility='visible';
}
}
xmlhttp1.send();
return false;
}
</script>
I tried two methods which both also cant show the browse button.
It should call out my visible on browse object as it's visible.. kindly advise.
http://jsfiddle.net/y3Bad/
A few things: you should include the visibility code inside of your removeDoc function, and bind the handler from javascript, not in markup. Also, your variable xmlhttp1 is an implicit global. Your removeDoc function takes a parameter, Doc, but you never pass anything to it. Finally, removeDoc makes an ajax call, which is asynchronous, so your line of code to show the browse button will not execute immediately, and may never execute at all if your ajax calls fails.
HTML:
<input type="button" id="show" name="show" value="show" />
JS:
​document.getElementById('show').onclick = function () {
// use display instead of visibility if you don't want the hidden element to take up space
// setting visibility to empty string will show the element
document.getElementById('browse').style.visibility = '';
};​
I use these two functions:
function hide(objId) {
document.getElementById(objId).style.display="none";
}
function show(objId) {
document.getElementById(objId).style.display="";
}
Maybe you can try to use jQuery, something like this:
http://jsfiddle.net/7fJuu/

How to call a function in javascript without HTML?

This is the function
function seeHTML(elem){
var htmlTxt=document.getElementsByTagName('html')[0].innerHTML.toString();
elem.value=htmlTxt;
}
to call i use HTML
<input type="button" value="See HTML" onclick="seeHTML(txt)">
how to call it from another function as document.write
document.write(seeHTML(txt));
-- im a javascript begginer
however i tried document.write but it prints the function data itself, it doesnt use the function, how to ask it to use it then print the return (result)
function foo(element) {
seeHTML(element);
}
function seeHTML(element) {
}
foo(document.getElementsById('element'));
in JavaScript code:
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", call_your_function_here);
</script>
Here we created an event listener it means when the document is fully loaded the function() will be called, using the same way you can add any event listener to any DOM object, ex. you have a button with id="test", var btest = document.getElementById('test'); then
btest.addEventListener('click', function() { //execute code if btest object was clicked });
Bottom line you should call your function when the document is fully loaded hence replace the call_your_function_here() with your function name and if you wanted to reference the same button your function was embedded in use this syntax to reference the button DOM object:
var buttonObj = document.getElementById(buttonID);
then supply buttonObj to your function's argument.

jQuery/MVC3 function html onclick only working once

Ok, i have a function that is called when in image is clicked. For some reason it is only calling one time when i click it and I'm a little puzzled as to why.
Here's my javascript (combined with a small amount of razor), essentially all it does is call a post method in the controller that returns a partial view and updates that partial view.
function mFunction() {
#{ x = x = 1; }
$.post('/Home/_MyPartial', { 'param1': "#x" }, function(result) {
$('.myUpdatedDiv').html(result);
$('.anotherDiv').empty();
$('.anotherDiv').append('#x');
});
}
Then i have my tag like this
Hello
It updates the view perfectly fine as i expect it to, with some goofy exceptions.
It does hit the controller every time it is clicked (multiple times). So i know it's working that way
The page itself does not get updated and nothing gets replaced a second time. The controller successfully returns the partial view, but the javascript only updates it once.
So i'd appreciate any help as to why it isn't updating more than once.
thanks
edit
Ok lets say i do this:
#{ int x = 0; }
<script type="text/javascript">
function tester() {
#{ x++; }
$('.H').empty();
$('.H').append('#x');
}
</script>
<div class="H"></div>
Click
Clicking on the tag will display '1' and clicking it on it will always display '1'. Does this have something to do with the razor code only rendering once or something? is there a way around it?
try this
<script type="text/javascript">
var indx = 1;//Set this to be the value from the model you want to display
function tester() {
$('.H').empty();
$('.H').append(indx);
indx++;
}
</script>
<div class="H"></div>
Click
Razor code is only run on the server, when the page has been downloaded all you have is the javascript with the Razor values output in place so your second example will look like this:
<script type="text/javascript">
function tester() {
$('.H').empty();
$('.H').append('1');
}
</script>
<div class="H"></div>
Click
This is why it will only ever append 1.
I suggest you use Firefox's Firebug or the Web Console (Ctrl+Shift+K) to look at the asynchronous calls. You'll know there if the browser is actually hitting the server on every click (and you can even see with what parameters whether POST or GET).
It looks like it should be contacting the server everytime, but because state is not kept between calls, you are always getting the same result after the 1st call (because you are always sending the same X value after the first call).

Categories

Resources