I initialize Uploadify using the following code:
$('#file1').uploadifive({
'buttonClass': 'upload-btn',
'uploadScript': '/Upload/',
'fileObjName': 'files',
'fileType': 'text/xml',
'formData': { 'uploadType': 'Crew' },
'onUploadComplete': function(file, data) {
var results = $.parseJSON(data);
if (results.error) {
var info = file.queueItem.find('span.fileinfo');
if (info) info.text(' - ' + results.error);
return;
}
window.location.href = '#Url.Content("~/Upload/Checkdata/")' + results.id;
}
});
This works, however I need to modify the formData property when a radio checkbox changes. So, I've tried this:
$('input[name=UploadType]:radio').change(function () {
$('#file1').uploadifive({ 'formData': this.value });
});
However, when that code runs, it breaks the Uploadify control (it now no longer uploads anywhere). I'm guessing because it completely re-initializes the control with all new settings.
How can I update just this one setting? I've read the Uploadify docs and none of them say anything about updating settings; just initializing and calling methods. Thanks!
I've figured out one solution, but not sure if it's the right way to do things (i.e., it might break in future versions of Uploadify).
Basically, it appears you can keep a reference to your configuration around, and update that object at any time:
var uploadifySettings = {
'buttonClass': 'upload-btn',
'uploadScript': '/Upload/',
'fileObjName': 'files',
'fileType': 'text/xml',
'formData': { 'uploadType': 'Crew' },
'onUploadComplete': function(file, data) {
var results = $.parseJSON(data);
if (results.error) {
var info = file.queueItem.find('span.fileinfo');
if (info) info.text(' - ' + results.error);
return;
}
window.location.href = '#Url.Content("~/Upload/Checkdata/")' + results.id;
}
}
$('input[name=UploadType]:radio').change(function () {
uploadifySettings.formData.uploadType = this.value;
});
$('#file1').uploadifive(uploadifySettings);
Related
I have a post that work well when I run from VS2015 debug:
$("#DisplayChartType").bind("change", function () {
$.post("../Employee/ChangeDisplayChartType", { displayChartType: $("#DisplayChartType").val() }, function (data) {
iDependOnMyParameter(data);
})
});
But post does not work once I have published to IIS. I tried using ../, / and ~/ in the post but none work. I searched web and found the approach below but I still get ARG1 being sent as a parameter instead of my javascript variable.
$("#DisplayChartType").bind("change", function () {
$.post("#Html.Action("ChangeDisplayChartType", "Employee", new { displayChartType = "ARG1" })".replace("ARG1",$("#DisplayChartType").val()) , function (data) {
iDependOnMyParameter(data);
})
});
How should I do this? I really would like to stay with $.post approach as that works nicely in VS.
You can try this code.
$("#DisplayChartType").bind("change", function () {
var chartType = $("#DisplayChartType").val();
var url="#Url.Action("ChangeDisplayChartType", "Employee", new { displayChartType = "ARG1" })";
$.post(url.replace("ARG1", chartType), function (data) {
iDependOnMyParameter(data);
})
});
So add it to the url
$.post("../Employee/ChangeDisplayChartType?displayChartType=" + encodeURIComponent($("#DisplayChartType").val()), function(){});
or change your original code to GET and the value will be added to the querystring.
You can use window.location.origin or document.location.origin to get the origin of your website, whether running in VS 2015 debug or on IIS.
So instead of doing
$.post("../Employee/ChangeDisplayChartType"
You can try
$.post(document.location.origin + "/Employee/ChangeDisplayChartType"
#OJ Raqueno put me on the right path.
At top of script I now declare "myPath". My website URL ends with "secure" so this test gives me the right path:
var myPath = document.URL;
if (!myPath.endsWith("secure")) {
myPath = "";
}
Then I do this:
$("#DisplayChartType").bind("change", function () {
$.post(myPath + "/Employee/ChangeDisplayChartType", { displayChartType: $("#DisplayChartType").val() }, function (data) {
alert($("#DisplayChartType").val());
iDependOnMyParameter(data);
})
});
This topic is covered in a few other questions, but I had some difficulty applying the suggested approaches into this use case. I have a checkbox list, where a user can select n sub-sites to publish their post to. since this list could grow to be 100+, I need an efficient way to perform an expensive task on each one. It's okay if it takes awhile, as long as Im providing visual feedback, so I planned to apply an "in progress" style to each checkbox item as its working, then move to the next item int he list once it is successfully published. Also note: I'm working in the WordPress wp_ajax_ hook but the PHP side of things is working well, this is focused on the JS solution.
This code is working right now (console.logs left in for debug), but I've seen multiple warnings against using async: true. How can I achieve a waterfall AJAX loop in a more efficient way?
//Starts when user clicks a button
$("a#as_network_syndicate").click( function(e) {
e.preventDefault(); //stop the button from loading the page
//Get the checklist values that are checked (option value = site_id)
$('.as-network-list').first().find('input[type="checkbox"]').each(function(){
if($(this).is(':checked')){
blog_id = $(this).val();
console.log(blog_id+' started');
$(this).parent().addClass('synd-in-progress'); //add visual feedback of 'in-progress'
var process = as_process_syndication_to_blog(blog_id);
console.log('finished'+blog_id);
$(this).parent().removeClass('synd-in-progress');
}
});
});
function as_process_syndication_to_blog(blog_id){
var data = {
"post_id": $('#as-syndicate_data-attr').attr("data-post_id"), //these values are stored in hidden html elements
"nonce": $('#as-syndicate_data-attr').attr("data-nonce"),
"blog_id": blog_id
};
var result = as_syndicate_to_blog(data);
console.log('end 2nd func');
return true;
}
function as_syndicate_to_blog(data){
$.ajax({
type : "post",
dataType : "json",
async: false,
url : ASpub.ajaxurl, //reference localized script to trigger wp_ajax PHP function
data : {action: "as_syndicate_post", post_id : data.post_id, nonce: data.nonce, blog_id: data.blog_id},
success: function(response) {
if(response.type == "success") {
console.log(response);
return response;
} else {
}
},
error: {
}
});
}
Indeed, doing synchronous AJAX request is bad because it will block the browser during the whole AJAX call. This means that the user cannot interact with your page during this time. In your case, if you're doing like 30 AJAX calls which take say 0.5 seconds, the browser will be blocked during 15 whole seconds, that's a lot.
In any case, you could do something following this pattern:
// some huge list
var allOptions = [];
function doIntensiveWork (option, callback) {
// do what ever you want
// then call 'callback' when work is done
callback();
}
function processNextOption () {
if (allOptions.length === 0)
{
// list is empty, so you're done
return;
}
// get the next item
var option = allOptions.shift();
// process this item, and call "processNextOption" when done
doIntensiveWork(option, processNextOption);
// if "doIntensiveWork" is asynchronous (using AJAX for example)
// the code above might be OK.
// but if "doIntensiveWork" is synchronous,
// you should let the browser breath a bit, like this:
doIntensiveWork(option, function () {
setTimeout(processNextOption, 0);
});
}
processNextOption();
Notice: as said by Karl-André Gagnon, you should avoid doing many AJAX requests using this technique. Try combining them if you can, it will be better and faster.
If you can't pass the whole block to the server to be processed in bulk, you could use a jQuery queue. This is using your sample code as a base:
var $container = $('.as-network-list').first();
$container.find('input[type="checkbox"]:checked').each(function(){
var $input = $(this);
$container.queue('publish', function(next) {
var blog_id = $input.val(),
$parent = $input.parent();
console.log(blog_id+' started');
$parent.addClass('synd-in-progress'); //add visual feedback of 'in-progress'
as_process_syndication_to_blog(blog_id).done(function(response) {
console.log(response);
console.log('finished'+blog_id);
$parent.removeClass('synd-in-progress');
next();
});
});
});
$container.dequeue('publish');
function as_process_syndication_to_blog(blog_id){
var data = {
"post_id": $('#as-syndicate_data-attr').attr("data-post_id"), //these values are stored in hidden html elements
"nonce": $('#as-syndicate_data-attr').attr("data-nonce"),
"blog_id": blog_id
};
return as_syndicate_to_blog(data).done(function(){ console.log('end 2nd func'); });
}
function as_syndicate_to_blog(data){
return $.ajax({
type : "post",
dataType : "json",
url : ASpub.ajaxurl, //reference localized script to trigger wp_ajax PHP function
data : {action: "as_syndicate_post", post_id : data.post_id, nonce: data.nonce, blog_id: data.blog_id}
});
}
I don't have a test environment for this so you may need to tweak it for your use case.
My javascript skills are limited and I'm having a problem with the structure of a series of functions which I think need callbacks. I've been reading a number of posts and tutorials but it's not sticking...yet..
On my page I have a pop up modal which contains an image. If the user clicks the edit button it's to be edited in aviary. Once that's completed the image properties get saved into a database and then the images within the modal box - and the underlying form - should get updated with the edited image.
My series of events starts with the modal opening:
$('#editImageLink2').click(function(event) {
aviaryOnClick('image2', $(this).data('mode'), function(image) {
#do final bits here
});
});
Modal pops up then if the user clicks the edit button this next function starts the editor:
function aviaryOnClick(source, mode) {
editedImage = doAviary(source);
if (editedImage) {
return true;
} else {
return false;
}
}
So - aviary pops up as expected. Then when the user saves the edited image I'm starting to have trouble:
The doAviary function looks like this:
function doAviary(source) {
console.log("hit doAviary", source);
var featherEditor = new Aviary.Feather({
apiKey: 'XXXXXXXX',
apiVersion: 3,
theme: 'dark',
tools: 'all',
displayImageSize: true,
maxSize: 1200,
onSave: function(imageID, newURL) {
//replace image in modal preview
var img = document.getElementById(imageID);
img.src = newURL;
if (newURL != undefined) {
storeImage(newURL, updateFormImage(imageData));
featherEditor.close();
return true;
}
},
onError: function(errorObj) {
alert(errorObj.message);
return false;
}
});
return featherEditor.launch({
image: source,
url: $('#' + source).attr('src')
});
}
So I'm trying to run storeImage in the onSave event, which should then run a callback to the update images with the image data.
My storeImage function:
function storeImage(newURL, imageData) {
var options = new Object();
options.aviaryURL = newURL;
options.mode = mode;
options.dbID = ($('#dbID').val()) ? $('#dbID').val() : null;
//console.log("store image options object:", options);
jQuery.ajax({
url: '/filemanager/aviary',
type: 'POST',
dataType: 'json',
data: options,
complete: function(xhr, textStatus) {
//called when complete
},
success: function(data, textStatus, xhr) {
//called when successful
console.log("finished store image", data);
$.cookie('asset_filename', data.image.filename);
$.cookie('asset_id', data.image.id);
imageData(data);
},
error: function(xhr, textStatus, errorThrown) {
//called when there is an error
imageData(false);
}
});
so IF the image is saved the data should be passed back to the callback. If it fails it's false
Then in the update image function
function updateFormImage(data) {
if (data.result == 'success') {
image = data.image;
#simple updates of elements in page
}
}
My current problem is that on save I'm getting an error imageData is not defined - I'm not sure why this is - if it's waiting for ajax to complete before passing back the data to the callback it should exist.
Why does this error happen?
What better ways are there to refactor this code and use callbacks correctly.
I originally had a callback on the first function but got an error callback function not defined
Confused.
Thanks
imageData is not defined into doAviary.
Also, updateFormImage should return something (imageData).
I have a simple regex function in jQuery to add an image tag to image URLs posted by users.
So that when a user posts for example www.example.com/image.jpg the image tag will be added so that user can see the image without clicking on the URL.
var hostname = window.location.hostname.replace(/\./g,'\\.');
var re = new RegExp('(http:\\/\\/[^' + hostname + ']\\S+[\\.jpeg|\\.png|\\.jpg|\\.gif])','g');
$(".texthold ").each(function() {
$(this).html($(this).html().replace(re, '<img src="$1" />'));
});
How can I check the file size of the image before allowing it to be viewable? So that if for example the image file size is bigger than 5MB the image will not be displayed and instead the URL will be shown.
var url = ...; // here you build URL from regexp result
var req = $.ajax({
type: "HEAD",
url: url,
success: function () {
if(req.getResponseHeader("Content-Length") < 5 * 1048576) // less than 5 MB?
; // render image tag
else
; // render URL as text
}
});
You will only be able to accomplish what you want if the server response for the images includes the appropriate Cross Origin Resource Sharing (CORS) header and a content-length header.
Additionally you will need to take into account the time required for the ajax requests to be fulfilled in your replacement loop.
Below is a jQuery (1.9.1) example which demonstrates what the final solution could look like. For it to work you will need to update the links to a server which returns proper CORS headers or disable security on your browser. The example is also on jsfiddle.
var largeImage = "http://eoimages.gsfc.nasa.gov/images/imagerecords/49000/49684/rikuzentakata_ast_2011073_lrg.jpg";
var smallImage = "http://eoimages.gsfc.nasa.gov/images/imagerecords/81000/81258/kamchatka_amo_2013143_tn.jpg";
var urls = [largeImage, smallImage];
var maxSize = 5000000;
$.each(urls, function(index, value) {
conditionalMarkupUpdater(value, maxSize);
});
var onShouldBeViewable = function () {
alert('This is a small image...Display it.');
};
var onShouldNotBeViewable = function () {
alert('This is a large image...Only provide the url.');
};
var onError = function() {
alert('There was an error...likely because of CORS issues see http://stackoverflow.com/questions/3102819/chrome-disable-same-origin-policy and http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/"');
};
function checkSize(url) {
var sizeChecker = new jQuery.Deferred();
var onSuccess = function (data, textStatus, jqXHR) {
var length = jqXHR.getResponseHeader('Content-Length');
if (!length) {
sizeChecker.reject("No size given");
} else {
sizeChecker.resolve(parseInt(length));
}
};
var onFailure = function (jqXHR, textStatus, errorThrown) {
sizeChecker.reject("Request failed");
};
$.when($.ajax({
type: "HEAD",
url: url
})).then(onSuccess, onFailure);
return sizeChecker.promise();
};
function conditionalMarkupUpdater(url, maxSize) {
$.when(checkSize(url)).then(
function (size) {
if (size <= maxSize) {
onShouldBeViewable();
} else {
onShouldNotBeViewable();
}
},
function (status) {
onError();
})
};
I'm currently writing an extension using Crossrider, and I need to load an image directly using the URL for doing some image processing on it. However, the onload event doesn't seem to be firing at all.
Am I doing something wrong or is it even possible to do that in a browser extension?
Here is the relevant piece of code:
var imga = document.createElement('img');
imga.src = obj.attr('href'); // URL of the image
imga.style.display = 'none';
imga.onload = function() {
alert('Image loaded');
var imgData = getImageData(imga, 0, imga.height - 3);
alert('Got Image data');
};
EDIT
Here is the full code
function readImage(obj)
{
console.log('Reading');
relayReadImage(obj.attr('href'));
}
function relayReadImage(link)
{
var dateObj = new Date();
var newlink = link + "?t=" + dateObj.getTime();
console.log(newlink);
appAPI.request.get(
{
url: newlink,
onSuccess: function(response, additionalInfo) {
console.log(response);
},
onFailure: function(httpCode) {
alert('GET:: Request failed. HTTP Code: ' + httpCode);
}
});
}
I'm a Crossrider employee and would be happy to help you. If I understand correctly, you are attempting to use the URL (href) of an object in a page's dom (obj.attr('href')) to load the image into a variable in the extension. You can achieve this using our cross-browser appAPI.request.get method in your extension.js file, as follows:
appAPI.ready(function($) {
appAPI.request.get({
url: obj.attr('href'),
onSuccess: function(response) {
var imgData = response;
console.log(imgData);
}
});
});
However, if I've misunderstood your question, please can you clarify the following:
What is the obj object is?
What are you trying to achieve, and in which context (in the Extension or on the Page)?