Fine Uploader referencing newly created DOM object in onComplete callback - javascript

I've been messing around with this for quite some time. The deeper I get the more tweaks I need to make. My biggest issue id being able to correctly reference the created li item once it is created.
For exampled once an image is uploaded a new li item is created. Then I reference this li element to make various changes. Such as add in thumb nail and custom buttons. This reference is required for various reasons.
Most of everything is working fine from deleting to error output etc. However the way I find reference to the corresponding li element is broken.
From what I can tell on complete is as such
onComplete(String id, String name, Object responseJSON, XMLHttpRequest xhr)
There is no much data on this but from I can gather the ID is a number represented the uploaded image in the order of the list. Possibly an internal list which would mirror the outputted list.
So I've been marrying up this id with the index id of the array of li elements. This has allowed me to the located the correct completed li element and manipulate it.
So this works fine. The issue is when I'm deleting images. Image are deleted and then the li elements removed. However the issue is that the onComplete ID does not marry up with the with the index within the list.
I'm using a custom delete function as my images are saved in a database and other reasons. I will also run into the same issue when prepoluating the list. Currently I plan to pre-output a copy of the list with the relevant data in exactly the same way. I cannot find any information on prepopulating the fineuplader.
So is there a way to accurately reference the newly complete li elements? Once that is constant on most browsers? How is the best way to prepopulate the list?
Really a simple reference within the oncomplete handler to the new dom li element would be perfect. Or anything similar. I'm surprised it does not exist. Maybe it does but I cannot find any info on it.
Thanks

I'm going to assume you are using the default Fine Uploader UI, and not FineUploaderBasic/core. In that case, it's quite easy to get a handle on the DOM element Fine Uploader creates for the associated file. For example, in an onComplete callback:
....
onComplete: function(id, name, response, xhrOrXdr) {
var listItemEl = this.getItemByFileId(id);
// do something with this element
}
I've provided a non-jQuery example since your example code does not seem to use jQuery, even though you have tagged this question as jQuery. In case you are using the jQuery plug-in, your code would look something like this:
$('#myFineUploaderContainer').on('complete', function(event, id, name, response, xhrOrXdr) {
var $listItem = $(this).fineUploader('getItemByFileId', id);
// do something with this jQuery object
});
Note that, in the above example, Fine Uploader versions 3.6 and older will return a Node/HTMLElement, while Fine Uploader 3.7 and newer will return the expected jQuery object. I wrote the above example assuming you are using 3.7.
For more information on this and other API methods, options, and callbacks, see the documentation at http://docs.fineuploader.com.

Related

jQuery on external text requesting images

I'm working on a chrome extension that uses jquery to parse the source of a page for specific things. In example I'm looking through Wikipedia to get the categories.
I get the source of the page via
chrome.tabs.executeScript(tabId, {
code: "chrome.extension.sendMessage({action: 'getContentText', source: document.body.innerHTML, location: window.location});"
}, function() {
if (chrome.extension.lastError)
console.log(chrome.extension.lastError.message);
});
I am then listening for this message (successfully) and then use jquery to parse the source key of the object, like so
if (request.action == "getContentText")
{
//console.log(request.source);
$('#mw-normal-catlinks > ul > li > a', request.source).each(function()
{
console.log("category", $(this).html());
});
}
This works as expected and logs a list of all the category links innerHTML. However the issue happens from that jQuery selector that it tries to load the images that are contained in request.source. This results in errors such as
GET chrome-extension://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Padlock-silver.svg/20px-Padlock-silver.svg.png net::ERR_FAILED
These are valid links, however they are being called (unneeded) from my extension with the chrome-extension:// prefix (which is invalid). I'm not sure why jquery would try to evaluate/request images from within source using a selector
I guess this is happening because Wikipedia uses relative paths on their images (instead of https:// or http://, simply // - so the content loaded is relative to the server). The requests are being made by jQuery and you can see here how to fix this issue (in future, please make sure to search SO more thoroughly).
A huge thank you to #timonwimmer for helping me in the chat. We both happened to find different solutions at the same time.
My solution was to use a regex to remove any occurances of the images. Via
var source = request.source.replace(/.*?\.wikimedia\.org\/.*?/g, "");
His was an answer on stack overflow already, that was derived from another answer. If you are interested this answer works perfectly
If you give jQuery a string with a complete element declaration it actually generates a new DOM element, similar to calling document.createElement(tagName) and setting all of the attributes.
For instance: var $newEl = $("<p>test</p>") or in your case img tag elements with $("<img/>"). That would get parsed and created as a new DOM HTML element and wrapped by jQuery so you can query it.
Since you are passing a complete and valid HTML string, it is parsing it into an actual DOM first. This is because jQuery uses the built in underlying document.querySelector methods and they act on the DOM not on strings -- think of the DOM as a database with indexes for id and class and attributes for querying. For instance, MongoDB cannot perform queries on a raw JSON string, it needs to first process the JSON into BSON and index it all and the queries are performed on that.
Your problem is less with jQuery and more so with how elements are created and what happens when attributes change for those elements. For instance, when the img elements are created with document.createElement('img') and then the src attribute is set with imgElement.src = "link to image" this automatically triggers the load for the image at location src.
You can test this out for yourself by running this in your JavaScript Developer Console:
var img = document.createElement('img');
img.src = "broken-link";
Notice that this will likely show and errors in your console after running stating that the image cannot be found.
So what you want, to ensure so it does not resolve the image's src, is to either
1) apply jQuery on an existing DOM (document.body, etc), or
2) let it parse and evaluate the string into a DOM and clean the string before hand (remove the img tags using Regex or something). Take a look at https://stackoverflow.com/a/11230103/2578205 for removing HTML tags from string.
Hope it works out!

jquery html() not setting div contents

I am making my first app using Parse.com for database storage, and I am using the Parse JavaScript SDK to make use of this database.
I am trying to populate a list of items from one of my database tables, and this table contains a field which is a pointer to an object of another class/table. I need to retrieve a field from this object in order to display the information properly.
However, Parse seems to require me to request each of these objects separately from my main query on the table. Anyway, so I make the request and have a success callback which uses jquery's .html() to set the contents of a div which is id'd by the id of the retreived object.
The problem is, after the work is done, the div is rendered empty. Although, oddly, I tried using calls to alert to get the contents of each div within the success callback, and the contents was not only correct after I had called .html() but also before I called it. Though, that's probably down to JavaScripts asynchronous function calls.
Here is the function in question:
function updateBudgets() {
var Budget = Parse.Object.extend("Budget");
var query = new Parse.Query(Budget);
query.equalTo("User", Parse.User.current());
//query.include(["Budget.Category"]); //I tried this to include the category object with the query response, but it didn't seem to work
query.find({
success: function(result) {
var opt = "<h2>Budgets</h2>";
var category, id;
for(var i = 0; i < result.length; i++) {
category = result[i].get("Category");
category.fetch({
success: function(cat) {
alert($('#' + cat.id).html());
$('#' + cat.id).text(cat.get("Name"));
alert($('#' + cat.id).html());
}
});
opt += makeBudget(category.id, parseFloat(result[i].get("Amount")/100), result[i].get("Balance"), result[i].id);
}
$('#budgets').html(opt);
}
});
}
I tried what the documentation seemed to suggest was the equivalent of an SQL JOIN operation using the .include() function on my query, but it didn't seem to work at all.
So, what I would like to know is either how I can debug my JavaScript such that I can get around this strange behaviour with .html() or how I can properly do this JOIN style operation with Parse. What Documentation I have found doesn't really go into a whole lot of detail.
I would be very grateful for any help.
Please consider the following "test guide" more as comment than an answer, because it just contains some console.log statements instead of an actual answer for your problem.
Anyway below are some issues I'd try to checkout:
do you receive an answer from the server following query.find
check is data fetched (inner query) from the server
check if category data is received successfully following fetch query
check if element with category id is found
error handling added for fetch and query
Also I noticed that you are using .text() method for setting the value. I think it'll work fine as long as the element in question is not a form input element. If that's the case, you probably have to you use .val() method.
The console.log test print outs that I added can be found at this Fiddle for updateBudgets() function. (Fiddle updated) I hope this helps :-)

jsTree: Bind to Domain Objects

I want to associate each node in my tree with a domain object. I was passing HTML data and manually storing the domain object in jQuery data:
$('li node description').data('obj', my_domain_object);
However, it seems that jsTree clears that data out during $('#jstree_div').jstree();.
So later, $('li node description').data('obj') is undefined.
What's the best practice to do this? (I'm guessing the principle would be the same for either HTML or JSON data)
jsTree keeps the data intact, but moves it for optimization reasons [1]. So in the callback, it must be accessed via data.node.data.some_key. In my example, the magic incantation was:
$('#jsTree_div').on('select_node.jstree', function (e, data) {
data.node.data.obj //... (instead of $('#node_id').data('obj'))
});
[1] "This is done because of speed. Attaching the data using jQuery's '.data()' every time a node is redrawn proved to be rather slow." - Ivan Bozhanov, jsTree creator https://groups.google.com/d/msg/jstree/w97E8uG_Bd0/enYklH-B1-cJ

using JQuery to fetch an html document and parse it into a DOM tree

So essentially I'm trying to build my own version of GitHub's tree slider. The relevant Javascript/JQuery code is:
// handles clicking a link to move through the tree
$('#slider a').click(function() {
history.pushState({ path: this.path }, '', this.href) // change the URL in the browser using HTML5 history module
$.get(this.href, function(data) {
$('#slider').slideTo(data) // handle the page transition, preventing full page reloads
})
return false
})
// binds hitting the back button in the browser to prevent full page reloads
$(window).bind('popstate', function() {
$('#slider').slideTo(location.pathname)
}
Ok, hopefully that's understandable. Now here's my interpretation of what's going on here, followed by my problem/issue:
The callback function for the GET request when navigating through the tree is the slideTo method, and an HTML string is passed in as an argument to that function. I'm assuming that slideTo is a function defined elsewhere in the script or in a custom library, as I can't find it in the JQuery documentation. So, for my purposes, I'm trying to build my own version of this function. But the argument passed into this function, "data", is just the string of HTML returned from the GET request. However, this isn't just a snippet of HTML that I can append to a div in the document, because if I perform the same GET request (e.g. by typing the url into a web browser) I would expect to see a whole webpage and not just a piece of one.
So, within this callback function that I am defining, I would need to parse the "data" argument into a DOM so that I can extract the relevant nodes and then perform the animated transition. However, this doesn't make sense to me. It generally seems like a Bad Idea. It doesn't make sense that the client would have to parse a whole string of HTML just to access part of the DOM. GitHub claims this method is faster than a full page reload. But if my interpretation is correct, the client still has to parse a full string of HTML whether navigating through the tree by clicking (and running the callback function) or by doing full page loads such as by typing the new URL in the browser. So I'm stuck with either parsing the returned HTML string into a DOM, or ideally only fetching part of an HTML document.
Is there a way to simply load the fetched document into a Javascript or JQuery DOM object so I can easily manipulate it? or even better, is there a way to fetch only an element with an arbitrary id without doing some crazy server-side stuff (which I already tried but ended up being too spaghetti code and difficult to maintain)?
I've also already tried simply parsing the data argument into a JQuery object, but that involved a roundabout solution that only seems to work half the time, using javascript methods to strip the HTML of unwanted things, like doctype declarations and head tags:
var d = document.createElement('html');
d.innerHTML = data;
body = div.getElementsByTagName("body")[0].innerHTML;
var newDOM = $(body);
// finally I have a JQuery DOM context that I can use,
// but for some reason it doesn't always seem to work quite right
How would you approach this problem? When I write this code myself and try to make it work on my own, I feel like no matter what I do, I'm doing something horribly inefficient and hacky.
Is there a way to easily return a JQuery DOM object with a GET request? or better, just return part of a document fetched with a GET request?
Just wrap it; jQuery will parse it.
$(data) // in your callback
Imagine you want to parse a <p> tag in your normal HTML web page. You probably would use something like:
var p = $('<p>');
Right? So you have to use the same approach to parse an entire HTML document and then, navigate through the DOM tree to get the specific elements you want. Therefore, you just need to say:
$.get(this.href, function(data) {
var html = $(data);
// (...) Navigating through the DOM tree
$('#slider').slideTo( HTMLportion );
});
Notice that it also works for XML documents, so if you need to download via AJAX a XML document from the server, parse the inner information and display it on the client-side, the method is exactly the same, ok?
I hope it helps you :)
P.S: Don't ever forget to put semicolons at the end of each JavaScript sentence. Probably, if you don't put them, the engine would work but it is better to be safe and write them always!

Checking a checkbox node programmatically with jsTree

In a tree built with jsTree, I have the text within the <a> tag sitting in a variable. I would like to check that node. How can I do so?
I am currently finding that node, using jQuery, and altering its class. However, this does not repair the parent node by making the parent undetermined in its class. I tried doing $('.colors').jstree("checkbox_repair"), but that didn't seem to do anything.
It would be great if someone could actually answer both those questions, since they are related to the same problem.
Here is a jsFiddle, illustrating the issue--> http://jsfiddle.net/thapar/5XAjU/
In js_tree there are .check_node ( node ) and .uncheck_node ( node ) functions, i think this is what you are asking for. Soe the documentation here: http://www.jstree.com/documentation/checkbox
This is an excerpt from the documentation in the link above, "how to perform an operation":
/* METHOD ONE */
jQuery("some-selector-to-container-node-here")
.jstree("operation_name" [, argument_1, argument_2, ...]);
/* METHOD TWO */
jQuery.jstree._reference(needle)
/* NEEDLE can be a DOM node or selector for the container or a node within the container */
.operation_name([ argument_1, argument_2, ...]);
So I think this syntax should work
$.jstree._reference(".colors").check_node('li#tree_3');
Also i am not sure you should be using a class to reference your tree. Probably use an ID to reference your tree, and then use this syntax:
$.jstree._reference("#colors").check_node('li#tree_3');
//EDIT: Please keep in mind that the newest version of jsTree doesn't have a function called _reference anymore. It got renamed to reference (without the leading underscore). (Last checked 24/08/2015 15:45 by #mkli90)
Link: https://www.jstree.com/api/#/?f=$.jstree.reference(needle)
If you want to check jsTree nodes on load for example like this:
$(document).ready(function()
{
$.jstree._reference('#menu').check_node('#pih2');
});
it does not work. For me works following:
$(function () {
$('#mainMenu1').bind('loaded.jstree', function(e, data){ //waiting for loading
$.jstree._reference('#menu').check_node('#pih2'); //check node with id pih2
$.jstree._reference('#menu').check_node('#pih6'); //check node with id pih6
});
});
I use jsTree 1.0-rc3 and JQuery 1.7.1.
Aloe
In current versions of jstree the following syntax works:
$("#my_tree").jstree("check_node", node_id);
I would like to add this solution, the select_node function does the same function as check_node. we can use it as follows;
$('#jstree_id').on('loaded.jstree', function() {
$("#jstree_id").jstree("select_node", ["list of nodes go here"]);
});
You can use it to select multiple nodes in an array or a single node.

Categories