There are a couple of points I was hoping for assistance on. I have the following code, by which I make a ajax call on page load, and either retrieve data successfully or handle any resulting error.
I am running JQuery 2.0.0, with JQuery UI 1.10.2 (PHPStorm seems to have trouble recognising later versions).
Relevant HTML:
<script type="text/javascript" src="inc/JQuery-2.0.0.js"></script>
<script type="text/javascript" src="inc/JQuery-UI-1.10.2.js"></script>
<script type="text/javascript" src="inc/core.js"></script>
...
<div id="feedback-dialog">
<div id="dialog-inner"><!-- dynamic content --></div>
</div>
</body>
Javascript:
var engine = 'engine.php',
feedbackWrapper = $('#feedback-dialog'),
feedbackInner = $('#dialog-inner');
function ftShowErrorMessage(e)
{
var error = e.toString(),
errorWrapper = $('<p id="error-message"/>');
$(errorWrapper).text(error);
$(feedbackInner).empty();
$(feedbackInner).append(errorWrapper);
$(feedbackWrapper).dialog({
title: 'An Error Occurred',
dialogClass: 'feedback-error',
buttons: [
{
'OK' : function() {
//do stuff
$(this).dialog('close');
}
}
]
});
}
$(document).ready(function()
{
(function(){
var args = {};
args.Request = 'get country ids with county options';
$.ajax({
type: 'POST',
url: engine,
data: args
})
.done(function(data)
{
try
{
var obj = JSON.parse(data);
if(!obj.hasOwnProperty('error'))
{
//continue
}
else
{
ftShowErrorMessage(obj.error);
}
}
catch(e)
{
ftShowErrorMessage(e)
}
})
.error(function( xhr, ajaxOptions, thrownError )
{
ftShowErrorMessage(thrownError)
});
})();
});
My aim here is to catch when the AJAX call cannot make a successful call, or returns a non-parse-able string, or returns an error flag within a successful call (signalling an error from the PHP script).
My first problem is that the dialog call just won't fire - no error or warning given. This is the case even when I tie it to a simple click event. If anyone can point out where this is failing, I'd be grateful (the wrapping function is being called, and I can pass and echo content to and from it - it just fails at the dialog call).
Secondly, can someone clarify for me the difference between the ajax success, done, and complete functions, and between error and fail (fail does not seem to be recognised by the IDE, although it appears in the docs, but that's probably a separate problem).
I'm not sure why your dialog isn't displaying, maybe this will work:
$(feedbackWrapper).dialog({
title: 'An Error Occurred',
dialogClass: 'feedback-error',
buttons: [
{
'OK' : function() {
//do stuff
$(this).dialog('close');
}
}
]
}).dialog("open");
I'm not sure why this would be needed, since autoOpen: true is the default. But if you've already closed the dialog from a previous error, I think you need to open it explicitly the next time.
Related
I need to access a js variable declared in one block of a html page into another block of the same html page just so I can stop a ajax call that is being made, but I don't know how can I access a variable that was declared into another block. I can't merge the two blocks, everything else is on the table.
<script>
$(function() {
var term = new Terminal('#input-line .cmdline', '#container output');
term.init();
});
</script>
<script>
term.ajaxHandler.abort();//but how can I access the variable term from the block above,this will be inside a button later
</script>
Thanks in advance
The way your code example is described, it's not possible to reuse that variable. Because it is not bound to the window object, it's bound to the function that is self-executed. It's an example of a "safe" way of libraries not intervening with your own code.
You can however, since I guess by the syntax it's jQuery, hook into the jQuery ajax handling. Based on your requirements, to stop an ajax call, you need to listen to all ajax requests.
You could take a look at the jQuery ajax hooks, https://api.jquery.com/category/ajax/.
You could end up with something like:
$(document).ajaxSend(function(event, xhr, settings){
if (settings.url === "/your/url/to/abort") {
xhr.abort();
}
});
just declare var term above the function declaration
var term
function test1(){
term = 'hello there'
test2()
}
function test2(){
console.log(term)
}
test1()
ok, I managed to solve, basically I created a function only to abort the ajax request like this:
this.abortAjax = () => {
requestHandler.abort();
}
and then accessing it within terminal.js itself using the term object that was instantiated beforehand. After working around the code I was able to keep everything inside the terminal script and not splitted in the two parts, getting something like this:
function ShowLoadingScreen () {
var customElement = $("<div>", {
"class" : "btn btn-danger btn-lg",
"text" : "Abort",
"onclick": "term.abortAjax()"
});
$.LoadingOverlay("show", {
//image : "/static/loading.gif",
background : "rgba(204, 187, 0, 0.8)",
imageAnimation : "rotate_right",
//imageAutoResize : true,
text : "Loading...",
custom : customElement
});
}
function request (command) {
...
requestHandler = $.ajax({
url: _url,
beforeSend: function () { ShowLoadingScreen(); }, // <Show OverLay
type: 'GET',
dataType: 'json',
success: function (response) {
...
},
complete: function () { HideLoadingScreen(); } //<Hide Overlay
}).fail(function (jqXHR, textStatus, error) {
...
});
ShowLoadingScreen();
}
Thanks, everyone.
I'm trying to develop reusable function based on a jQuery dialog form, as a replacement for JS prompt. I need user to input data before other JS code is executed (the AJAX request that follows depends on the input of the user).
The function should read one text field and return the value entered if OK button or Return are pressed.
I managed to create the function with callback and it is working, except it doesn't wait for the user to react and the code after the function is executed.
I understand that jQuery calls are asynchronous and tried versions with deferred option, but that didn't work either.
Is there any way to make my code wait for the user input before it continues executing? Of course, the ideal solution would be to use like var userInput = getTxtField(....);
Update:
The function getTxtField is triggered by other user actions (buttons): renameFile, renameFolder, addFile etc.
Update #2 Problem solved
Thanks to #SuperPrograman's suggestion I started thinking with the logic of asynchronous execution. The original code was developed with value = prompt(...) approach and the AJAX code was at the bottom of the single function. I simply took the AJAX code in a separate function and now it works as expected. I've updated the JS code at the bottom.
My code is the following
....
<div class='hidden' id='dialog-newName' title=''>
<label id='label-txtField' for="txtField"></label>
<input type="text" name="txtField" id="txtField" value="" class="text ui-widget-content ui-corner-all">
</div>
....
function getTxtField (title, label, defVal, callBack) {
$('#label-txtField').text(label);
$('#txtField').val(defVal);
$( '#dialog-newName' ).dialog({
modal: true, closeOnEscape: false,
height: 200, width: 500,
title: title,
buttons: {
OK: function() {
callBack('OK', $('#txtField').val());
$(this).dialog( "close" );
},
Cancel: function() {
$('#txtField').val('');
//callBack('Cancel', ''); // not necessary
$(this).dialog( "close" );
}
},
});
}
...
switch (action) {
case 'action1':
// user pressed button for Action1
console.log('before dialog getTxtField ');
getTxtField('Action1', 'Label1', 'defaultValue1', function(buttonP, result) {
console.log(buttonP + ' value=' + result); // prints OK
});
// executed before input finished
console.log('after dialog getTxtField returnVal=' + newName + ')');
break;
case 'action2':
// ....
break;
}
// proceed with AJAX request for selected action
...
//=========================
// working code
//=========================
$('.selector').click ( function() {
var frmId = $(this).closest('form').attr('id');
var action = $(this).attr('ajaxAction');
var form = $('#theForm')[0];
var ajaxData = new FormData(form);
switch action {
case 'actions that do not require function getTxtField':
ajaxData.append(specific data for the action);
ajaxCall (frmId, ajaxData);
break;
case 'actions that with function getTxtField':
getTxtField('Titlexx', 'Labelxx', 'defaultValuexx', function(buttonP, result) {
// process result
ajaxData.append(specific data for the action);
ajaxCall (frmId, ajaxData);
});
break;
}
})
function ajaxCall (id, data) {
// standard ajax code
}
Since my comment helped, I'll add answer for quick access.
Basically you want to format code so everything that comes after dialog runs inside callback directly or is initiated from the callback.
So assuming a simple getTxtField prompt method taking a message and a callback function, instead of:
stuffBeforePrompt();
getTxtField('stuff', function() { });
stuffAfterPrompt();
You'll just need:
stuffBeforePrompt();
getTxtField('stuff', function() {
stuffAfterPrompt();
});
Perhaps you could make some solution using 'threads' or workers where you run prompt on separate thread and sleep main until result (or vice versa); but I doubt that would be worth the slight usage convenience.
I am currently facing a strange behavior with my SAPUI5 coding when I do a DELETE with the model (sap.ui.model.odata.v2.ODataModel). I wanted to implement a list, which displays some "Favorites" in a SelectDialog. By pressing the icon, the users can delete a favorite. For the item itself I used a FeedListItem, which is triggering the iconPress-Event _handleIconPressDelete.
<FeedListItem icon="sap-icon://delete" iconActive="true" iconPress="_handleIconPressDelete" text="{Name}" sender="{ID}"/>
The event looks like this:
_handleIconPressDelete: function(oEvent) {
var oModel = oEvent.getSource().getModel();
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
}
But when this event is triggered, two identical delete requests are generated and causing an error, because with the current changeset coding in the backend, I am only allowed to do one request at the same time.
The strange thing is, this behavior only appears when I open the dialog the first. When I close and reopen it, everything works fine.
Do you have any ideas, what I might do wrong here so that two requests are generated? I also checked, if the event is triggered multiple times, but that wasn't the case.
As current workaround I am using deferredGroups as shown in the snipped below so that the two request are separated, but I think there must be better ways to solve this.
_handleIconPressDelete: function(oEvent) {
var oModel = oEvent.getSource().getModel();
oModel.setDeferredGroups(["group1"]);
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
groupId: "group1",
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
oModel.submitChanges({
groupId: "group1"
});
}
I too experienced the same issue where the event associated with iconPress of FeedListItem triggers twice though user click only once..
Following is a workaround which you can implement using custom coding.
Declare the following variable in view controller's onInit()
this._bFirstTrigger = true;//SETTING FOR THE FIRIST TIME
Use this in FeedListItem's iconPress event to ensure that the relevant code executes only once as follows:
_handleIconPressDelete: function(oEvent) {
if (this._bFirstTrigger) {
var oModel = oEvent.getSource().getModel();oModel.setDeferredGroups(["group1"]);
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
groupId: "group1",
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
oModel.submitChanges({
groupId: "group1"
});
}
this._bFirstTrigger = false;
}
else{
this._bFirstTrigger = true;
}
Regards,
Fahad Hamsa
I have a problem with CKEditor version 4.7.0. I'm using jQuery ajax to get and save information. The problem now is that Chrome v 58.0.3029.110 shows me an error in the console - Cannot read property 'on' or undefined -, so I want to know how can I solve this or what kind of problem is. Here is my code:
function formService(id)
{
clearFields(); // clear all the fields in the form
// Show and hide form and record listing
$("#areaForm").css("display", "block");
$("#areaList").css("display", "none");
if (id != 0)
{
$("#id").val(id);
$.ajax({
url: 'admin/'+controller+'/ajaxQueryRecord',
type: 'post',
dataType: 'json', // to get a json object with all fields with information
data: {id: id},
})
.done(function(json) {
CKReset(json.content); // A function below of this code
delete json.content;
// A global function that extract information and are assigned to their fields
// in the form
assign_JSON_to_Fields(json);
$("#btnSubmit").val("Update"); // Only to change the text of the button
})
.fail(function() {
console.log("error");
});
} else {
$("#btnSubmit").val("Add");
}//if
}//fn
// Clean all the fields in the form
function clearFields()
{
$("#frmService input[type=text]").val("");
$("#id").val(0);
$('textarea').val('');
CKReset('');
}//fn
// Function that reset content destroying CKEditor instance
// and create (replace) a new one
function CKReset(content)
{
console.log(CKEDITOR.instances['content']);
if (CKEDITOR.instances['content']) {
CKEDITOR.instances['content'].destroy(true);
}//if
CKEDITOR.replace('content');
CKEDITOR.instances['content'].setData(content);
}//fn
Does somebody knows how to solve this detail? Any help will be appreciated! Thank you!
I think I've found the answer of it, because the main problem was that CKEditor was not ready when I load ajax data, and didn't recognize the field of "content", then the console throw the error. But with this lines of code I don't have any problem to load content and the script waits until the instance of CKEditor is ready:
I had to delete this lines:
CKReset(json.content); // A function below of this code
delete json.content;
And replace them with this lines:
CKEDITOR.instances['content'].on("instanceReady", function(event) {
CKReset(json.content);
delete json.content;
});
And the other code is the same.
Try to use try/catch statement to destroy CKeditor :
console.log(CKEDITOR.instances['content']);
if (CKEDITOR.instances['content']) {
try {
CKEDITOR.instances['content'].destroy(true);
} catch (e) { }
}
CKEDITOR.replace('content');
CKEDITOR.instances['content'].setData(content);
I have a JavaScript file here http://www.problemio.com/js/problemio.js and I am trying to place some jQuery code into it that looks like this:
$(document).ready(function()
{
queue = new Object;
queue.login = false;
var $dialog = $('#loginpopup')
.dialog({
autoOpen: false,
title: 'Login Dialog'
});
var $problemId = $('#theProblemId', '#loginpopup');
$("#newprofile").click(function ()
{
$("#login_div").hide();
$("#newprofileform").show();
});
// Called right away after someone clicks on the vote up link
$('.vote_up').click(function()
{
var problem_id = $(this).attr("data-problem_id");
queue.voteUp = $(this).attr('problem_id');
voteUp(problem_id);
//Return false to prevent page navigation
return false;
});
var voteUp = function(problem_id)
{
alert ("In vote up function, problem_id: " + problem_id );
queue.voteUp = problem_id;
var dataString = 'problem_id=' + problem_id + '&vote=+';
if ( queue.login = false)
{
// Call the ajax to try to log in...or the dialog box to log in. requireLogin()
}
else
{
// The person is actually logged in so lets have him vote
$.ajax({
type: "POST",
url: "/problems/vote.php",
dataType: "json",
data: dataString,
success: function(data)
{
alert ("vote success, data: " + data);
// Try to update the vote count on the page
//$('p').each(function()
//{
//on each paragraph in the page:
// $(this).find('span').each()
// {
//find each span within the paragraph being iterated over
// }
//}
},
error : function(data)
{
alert ("vote error");
errorMessage = data.responseText;
if ( errorMessage == "not_logged_in" )
{
//set the current problem id to the one within the dialog
$problemId.val(problem_id);
// Try to create the popup that asks user to log in.
$dialog.dialog('open');
alert ("after dialog was open");
// prevent the default action, e.g., following a link
return false;
}
else
{
alert ("not");
}
} // End of error case
}
}); // Closing AJAX call.
};
$('.vote_down').click(function()
{
alert("down");
problem_id = $(this).attr("data-problem_id");
var dataString = 'problem_id='+ problem_id + '&vote=-';
//Return false to prevent page navigation
return false;
});
$('#loginButton', '#loginpopup').click(function()
{
alert("in login button fnction");
$.ajax({
url:'url to do the login',
success:function() {
//now call cote up
voteUp($problemId.val());
}
});
});
});
</script>
There are two reasons why I am trying to do that:
1) I am guessing this is just good practice (hopefully it will be easier to keep track of my global variables, etc.
2) More importantly, I am trying to call the voteUp(someId) function in the original code from the problemio.js file, and I am getting an error that it is an undefined function, so I figured I'd have better luck calling that function if it was in a global scope. Am I correct in my approach?
So can I just copy/paste the code I placed into this question into the problemio.js file, or do I have to remove certain parts of it like the opening/closing tags? What about the document.ready() function? Should I just have one of those in the global file? Or should I have multiple of them and that won't hurt?
Thanks!!
1) I am guessing this is just good practice (hopefully it will be
easier to keep track of my global variables, etc.
Yes and no, you now have your 'global' variables in one spot but the chances that you're going to collide with 'Global' variables (ie those defined by the browser) have increased 100% :)
For example say you decided to have a variable called location, as soon as you give that variable a value the browser decides to fly off to another URL because location is a reserved word for redirecting.
The solution to this is to use namespacing, as described here
2) More importantly, I am trying to call the voteUp(someId) function
in the original code from the problemio.js file, and I am getting an
error that it is an undefined function, so I figured I'd have better
luck calling that function if it was in a global scope. Am I correct
in my approach?
Here's an example using namespacing that will call the voteUp function:
(function($) {
var myApp = {};
$('.vote_up').click(function(e) {
e.preventDefault();
myApp.voteUp();
});
myApp.voteUp = function() {
console.log("vote!");
}
})(jQuery);
What about the document.ready() function? Should I just have one of
those in the global file? Or should I have multiple of them and that
won't hurt?
You can have as many document.ready listeners as you need, you are not overriding document.ready you are listening for that event to fire and then defining what will happen. You could even have them in separate javascript files.
Be sure your page is finding the jquery file BEFORE this file is included in the page. If jquery is not there first you will get function not defined. Otherwise, you might have other things conflicting with your jquery, I would look into jquery noConflict.
var j = jQuery.noConflict();
as seen here:
http://api.jquery.com/jQuery.noConflict/
Happy haxin
_wryteowl
Extending what KreeK has already provided: there's no need to define your "myApp" within the document ready function. Without testing, I don't know off the top of my head if doing so is a potential source for scope issues. However, I CAN say that the pattern below will not have scope problems. If this doesn't work, the undefined is possibly a script-loading issue (loading in the right order, for example) rather than scope.
var myApp = myApp || {}; // just adds extra insurance, making sure "myApp" isn't taken
myApp.voteUp = function() {
console.log("vote!");
}
$(function() { // or whatever syntax you prefer for document ready
$('.vote_up').click(function(e) {
e.preventDefault();
myApp.voteUp();
});
});