The getButton method is returning undefined - fine-uploader

attempting to call $(this).fineUploader("getButton", id); in the submit event handler and getting undefined as a result.
I assume the buttons are being tracked since access to the button is available within the validate and upload events. However, I really would like to know which button was clicked during the submit event so I can set parameters for the specific file upload. The validate event has no file id present to associate specific parameters
In Response to Comments, additional information:
Fineuploader Version 4.1.1
I have tried the scenario in many configurations and getButton method call never works in the submit handler
myfineuploader.on('submit', function(event, id, name) {
var button = $(this).fineUploader('getButton', id);
console.log(button); // Button always shows undefined here
}
The buttons are defined as spans outside of the template, setup like this in the config:
button: $("#button1"),
extraButtons: [
{
element: $("#button2")
}
]

The button is not associated with the file until after the submit event callback has completed. This was done to ensure that mappings were created only for files that passed all possible validation steps, since it is possible to reject a file in your "submit" handler as well. After some thought, it may be best to create this button to file mapping as soon as we have created an ID for this file internally. I've created an item in our issue tracker to deal with this.
If you move your logic into a "submitted" event handler instead, you should be good to go.

Related

Calculation from Value-List in Archer GRC based on date (with non-empty validation)

I've been trying to implement what's been asked in this Stack Overflow question, here:
Calculation for status in Archer GRC based on date
Trying to create a status field based on a number of Value Lists that
users select from, but a request has been made that we check a date
field for a value to ensure an estimated date has been set so that the
calculation can determine if the status of the record is "In
Progress", "Late" or "Not Started".
...and now, I have a requirement for an actual popup warning message of some sort to prompt the user to make sure the date field is not blank.
How would I add this functionality?
In order to deliver the functionality you are looking for you have to use a "Custom Object". It is an object you put on the layout of the application in Archer that contains JavaScript code. This code will be executed as soon as the form of the application is loaded. There is a special type of the field "Custom Object" available in the Layout editor for each application in the Application Builder in Archer.
Note - I don't recommend to use custom objects in general and neither RSA Support. Every time you modify the layout in the given application, you have retest and sometimes correct IDs for your custom object. You can write an ID independent custom object and use field names, but in this case custom object will have more code. I prefer to make custom objects as short as possible.
Your custom object should do the following:
Override the behavior of the "Save" and "Apply" button in the top tool bar available for every application form in Archer.
Once "Save" and "Apply" buttons are "overwritten", every time they are clicked on your function will be called. So you need to create a click handler function.
Your click handler function will check values user is required to populate and will either return warning, or will call the original handler for "Save/Apply" buttons.
This is a code template you can start with:
<script type="text/javascript">
// ids are used to locate buttons
var buttons_ids = [
"master_btnSave", // "Save" button ID
"master_btnApply" // "Apply" button ID
];
// parameters are used in the "onclick" default handlers to call original handlers
var buttons_parameters = [
"master$btnSave", // "Save" parameter
"master$btnApply" // "Apply" parameter
];
document.getElementById(buttons_ids[0]).onclick = function(){ Validator_of_required_fields(buttons_parameters[0])};
document.getElementById(buttons_ids[1]).onclick = function(){ Validator_of_required_fields(buttons_parameters[1])};
// end of the script body
//==== Validator function attached to Save and Apply buttons
function Validator_of_required_fields(parameter){
// ids of the input fields to validate
var inputs_to_validate_ip_address = [ "master_DefaultContent_rts_XXX_YYY_t" ];
// jQuery selector is used here. Archer v5.x has jQuery library loaded by default
// you will need to modify this selector
var field_value = $('#'+inputs_to_validate_ip_address[0]+':first').val();
if(field_value.length = 0) {
// Here you are calling Archer Warning function
var msg = "[Text to display to user]";
var title = 'Required Field';
WarningAlert(msg,title);
return false;
};
// default onclick processor
ShowAnimationAndPostback(parameter);
return false;
};
Some comments on this code:
You will need to modify the validation function to work with values stored in the fields you need.
I used a rather 'unusual' way to override the behavior of the "Save" and "Apply" buttons using the following code:
document.getElementById(buttons_ids[0]).onclick = function(){ bla, bla, bla }There are simpler way to do the same, but this way custom object works fine in IE8-11, FF, Chrome and Opera. Let me know if you find a simpler way to override buttons that is browser agnostic.
Function WarningAlert(msg,title); is a build-in Archer warning message function. It worked fine in Archer v5.4. You might need to use simple JavaScript Alert function if WarningAlert doesn't work in your version of Archer.
Note that behavior of the "Save" and "Apply" buttons might be overwritten back to default in case if user opens up any pop-up dialog windows to populate a value list or cross-reference field. If that is the case, you will have to wrap the code provided into another function and attach it to the OnLoadWindow event (or similar).
I try to avoid using any JavaScript libraries in my custom objects. This way it is simpler to support them and you have less dependencies. I used jQuery in the provided example only because Archer already uses this library once the page is loaded.
Flak, make sure to test your custom object very well and good luck!

How to get access to Current view model methods from Shell.js

I have a button in shell.html, on click of that button I need to post the current view model.
I can determine the current view model's Module Id, but how can I get a reference to it so that I can invoke its methods from Shell.js
For eg, if my current view model has a method called "SubmitApplication"
I would like to call or trigger this method from Shell.js on click of the button in Shell.html
Please help.
Thanks
Consider using Durandal's event system for cross module communication.
http://durandaljs.com/documentation/Leveraging-Publish-Subscribe.html
By default app has event capabilities included, which would allow you to do something along the following line:
shell.js
submitOnClick: function(){
app.trigger('application:submit', payload);
}
viewmodel
app.on('application:submit').then(function(payload){
//do something with payload
});

jQuery 'on' not registering in dynamically generated modal popup

I was under the impression that jQuery's on event handler was meant to be able to 'listen' for dynamically created elements AND that it was supposed to replace the behavior of live. However, what I have experienced is that using on is not capturing the click event whereas using live is succeeding!
The tricky aspect of my situation is that I am not only dynamically creating content but I'm doing it via an AJAX .get() call, and inserting the resultant HTML into a modal .dialog() jQueryUI popup.
Here is a simplified version of what I was trying to accomplish (wrapped in $(document).ready(...) ):
$.get("getUserDataAjax.php", queryString, function(formToDisplay) {
$("#dialog").dialog({
autoOpen: true,
modal: true,
buttons...
}).html(formToDisplay);
});
$(".classThatExistsInFormToDisplay").on("click", function() {
alert("This doesn't get called");
});
From the documentation for on I found this which which was how I was approaching writing my on event:
$("p").on("click", function(){
alert( $(this).text() );
});
However, for some reason, live will work as I expect -- whereas on is failing me.
This isn't a question for "how can I make it work" because I have found that on will succeed (capture clicks) if I declare it inside the function(formToDisplay) callback.
My question is: what is wrong with on that it isn't finding my dynamically created elements within a modal popup? My jQuery instance is jquery-1.7.2. jQueryUI is 1.8.21.
Here are two jsFiddles that approximate the issue. Click the word "Test" in both instances to see the different behavior. The only difference in code is replacing on for live.
Where the click is captured by live.
Where the click is NOT captured by on (click 'Test - click me' to see nothing happen).
I realize I may just be using on inappropriately or asking it to do something that was not intended but I want to know why it is not working (but if you have something terribly clever, feel free to share). Thanks for your wisdom!
Update / Answer / Solution:
According to user 'undefined', the difference is that on is not delegated all the way from the top of the document object whereas live does/is.
As Claudio mentions, there are portions of the on documentation that reference dynamically created elements and that what you include in the $("") part of the query needs to exist at runtime.
Here is my new solution: Capture click events on my modal dialog, which, although it does not have any content when the event is created at runtime, will be able to find my content and element with special class that gets generated later.
$("#dialog").on("click", ".classThatExistsInFormToDisplay", function() {
... //(success! Event captured)
});
Thanks so much!
live delegates the event from document object, but on doesn't, if you want to delegate the event using on method, you should delegate the event from one of static parents of the element or document object:
$(document).on("click", ".clickHandle", function() {
alert("Content clicked");
});
The problem is that the element to which you attach the event has to exist.
You have to use on like this to capture clicks on p tags created dynamically
$("#existingContainerId").on("click", "p", function(){
alert( $(this).text() );
});
if you have no relevant existing container to use, you could use $("body") or $(document)
If selector is omitted or is null, the event handler is referred to as direct or directly-bound. The handler is called every time an event occurs on the selected elements, whether it occurs directly on the element or bubbles from a descendant (inner) element.
When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next
Take a look to section Direct and delegated events here for more details

jQuery Showing an Ajax loader during transmission & Prevent Multiple Submits

I have an app that has several different types of form elements which all post data to the server with jQuery AJAX.
What I want to do is:
Show a loader during AJAX transmission
Prevent the user from submitting twice+ (clicking a lot)
This is easy to do on a one off basis for every type of form on the site (comments, file upload, etc). But I'm curious to learn if that is a more global way to handle this?
Something that's smart enough to say:
If a form is submitting to the server and waiting for a response, ignore all submits
Show a DISABLED class on the submitted / clicked item
Show a loading class on the class="spinner" which is closest to the submit item clicked
What do you think? Good idea? Done before?
Take a look at the jQuery Global Ajax Event Handlers.
In a nutshell, you can set events which occur on each and every AJAX request, hence the name Global Event Handlers. There are a few different events, I'll use ajaxStart() and ajaxComplete() in my code sample below.
The idea is that we show the loading, disable the form & button on the ajaxStart() event, then reenable the form and hide the loading element inside the ajaxComplete() event.
var $form = $("form");
$form.ajaxStart(function() {
// show loading
$("#loading", this).show();
// Add class of disabled to form element
$(this).addClass("disabled");
// Disable button
$("input[type=submit]", this).attr("disabled", true);
});
And the AJAX complete event
$form.ajaxComplete(function() {
// hide loading
$("#loading", this).hide();
// Remove disabled class
$(this).removeClass("disabled");
// Re-enable button
$("input[type=submit]", this).removeAttr("disabled");
});
You might need to attach to the ajaxError event as well in case an AJAX call fails since you might need to clean up some of the elements. Test it out and see what happens on a failed AJAX request.
P.S. If you're calling $.ajax or similar ($.getJSON), you can still set these events via $.ajaxStart and $.ajaxComplete since the AJAX isn't attached to any element. You'll need to rearrange the code a little though since you won't have access to $(this).
I believe you have to do 2 for sure and 3 to improve usability of your app. It is better to keep backend dumb but if you have a security issue you should handle that too.

Google Chrome Extension - How can I include a content script more than once?

I've been working on Chrome Extension for a website for the past couple of days. It's coming along really nicely but I've encountered a problem that you might be able to help with.
Here's an outline of what the extension does (this functionality is complete):
A user can enter their username and password into the extensions popup - and verify their user account for the particular website
When a user browses http://twitter.com a content script is dynamically included that manipulates the DOM to include an extra button next to each tweet displayed.
When a user clicks this button they are presented with a dialog box
I've made a lot of progress but here is my problem:
When a user visits Twitter the content script is activated and all tweets on the page get my new button - but if the user then clicks 'More...' and dynamically loads the next 20 tweets... these new additions to the page DOM do not get affected by the content script (because it is already loaded).
I could add an event listener to the 'More...' button so it then triggers the original content script again (and adds the new button) but i would have to predict the length of twitter's ajax request response.
I can't tap into their Ajax request that pulls in more tweets and call my addCurateButton() function once the request is complete.
What do you think is the best solution? (if there is one)
What you want to do is to re-execute your content-script every time the DOM is changed. Luckily there is an event for that. Have a look at the mutation event called DOMNodeInserted.
Rewrite your content script so that it attaches an event listener to the body of the DOM for the DOMNodeInserted event. See the example below:
var isActive = false;
/* Your function that injects your buttons */
var inject = function() {
if (isActive) {
console.log('INFO: Injection already active');
return;
}
try {
isActive = true;
//inject your buttons here
//for the sake of the example I just put an alert here.
alert("Hello. The DOM just changed.");
} catch(e) {
console.error("ERROR: " + e.toString());
} finally {
isActive = false;
}
};
document.body.addEventListener("DOMNodeInserted", inject, false);
The last line will add the event listener. When a page loads the event is triggered quite often so you should define a boolean (e.g. var isActive), that you initialize to false. Whenever the inject function is run check whether isActive == true and then abort the injection to not execute it too often at the same time.
Interacting with Ajax is probably the hardest thing to coax a content script to do, but I think you’re on the right track. There are a couple different approaches I’ve taken to solving this problem. In your case, though, I think a combination of the two approaches (which I’ll explain last) would be best.
Attach event listeners to the DOM to detect relevant changes. This solution is what you’ve suggested and introduces the race condition.
Continuously inspect the DOM for changes from inside a loop (preferably one executed with setInterval). This solution would be effective, but relatively inefficient.
The best-of-both-worlds approach would be to initiate the inspection loop only after the more button is pressed. This solution would both avoid the timing issue and be efficient.
You can attach an event-handler on the button, or link that is used for fetching more results. Then attach a function to it such that whenever the button is clicked, your extension removes all the buttons from DOM and starts over inserting them, or check weather your button exists in that particular class of DOM element or not and attach a button if it doesn't.

Resources