As far as I can see, there is no "meaningful API documentation" that I can find either. There are, however, various tutorials online on putting together GUI extensions, for example:
Validating content on save: http://www.curlette.com/?p=913
Various useful snippets: https://github.com/TridionPractice/tridion-practice/wiki/AnguillaSnippets
Bear in mind that the CME offers functionality for both of your "How do I?" questions, so unless you're extending what the GUI does or making some kind of bookmarklet, it is likely that either the Event System or Core Service API might be a better fit.
Please bear in mind I've come to this answer by fiddling, so it may well not be "best practice"!
Working in the browser console:
Search for a component by it's name
You need an object to search, and to load that object in order to gain access to its properties. This seems a common theme in Anguilla. So, let's say you want to search a publication:
var publication = $tcm.getItem(publicationId);
If you now type publication.getSearchList
you'll get the getSearchList function returned. You can see that it is a function with four parameters, the first of which is a Tridion.ContentManager.ListSearchFilter
. This info is also in the "auto-docs", whre the other parameters are detailed.
For ListSearchFilter
you will see that it has properties columns, conditions, constructor, prototype. There is no useful information about what "conditions" is, but a little further digging and watching the network panel in the browser console suggests it's pretty much a clone of SearchQueryData
in the Core Service API.
var filter = {conditions: {searchIn: publicationId, searchQuery: "some search", recursive: true}};
var results = publication.getSearchList(filter);
You have to load the results:
results.load();
You can then work with the results, so results.getCount()
gets you a count of the results, results.getItems()
gets you an array of the results. What is returned is just stub data, so you may need to load
individual results if you need more than that data.
Upload files to a Multimedia Component
Firstly, remember that any action involving files on the user's machine must be initiated by the user selecting a file and must involve a click. Browser security rules. With that in mind, remember there is "New Multimedia Component" and "Upload Multimedia Component" in the GUI already, and you can already load and save files when modifying Multimedia Components ... and attach Events to them.
Like the Core Service API, when you upload a file, it gets uploaded to a temporary location on the server. The request you make to create or modify a MM Component has to reference that location. If you watch the upload activity in the browser console, you can see that it posts to FileUpload.aspx, and if you look at what it returns, you get an HTML document with the information you need.
Making the assumption that you want to make your own upload interface, then you could do an Ajax POST to FileUpload.aspx, grab the data returned and then use that to save or create a MM Component. Here's a stub for an upload form; has to be run in the console (or a bookmarklet) from within Tridion:
var formWindow = window.open();
var formDocument = formWindow.document;
var formBody = formDocument.body;
var form = formDocument.createElement("form");
var input = formDocument.createElement("input");
input.setAttribute("name", "LoadFromDisk_upload_file");
input.setAttribute("type", "file");
input.setAttribute("id", "uploader");
form.setAttribute("action", location.protocol + "//" + location.host + "/WebUI/Core/Controls/UploadControl/FileUpload.aspx");
form.setAttribute("enctype", "multipart/form-data");
form.appendChild(input);
formBody.appendChild(form);
var uploader = formDocument.getElementById("uploader");
If you attach an event to uploader
, then you can upload a file when the field changes. Note that it must be via a File input and done by the user (otherwise anyone could upload passwords.txt from your desktop, not that anyone I know has one of those!).
var nameOnServer = "";
var nameOnClient = "";
uploader.onchange = function() {
var data = new FormData();
data.append(uploader.getAttribute("name"), uploader.files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", location.protocol + "//" + location.host + "/WebUI/Core/Controls/UploadControl/FileUpload.aspx", false);
xhr.onreadystatechange = function(e) {
if(xhr.readyState == XMLHttpRequest.DONE) {
console.log("Uploaded");
response = xhr.response;
var parser = new DOMParser();
var responseHTML = parser.parseFromString(response, "text/html");
nameOnServer = responseHTML.getElementById("nameOnServer").value;
nameOnClient= responseHTML.getElementById("nameOnClient").value;
//Do stuff
}
}
xhr.send(data);
}
Once you have the name on the server, you can upload the file. Clearly you should only call this when you have the data you need, i.e. from within the readystatechange handler.
If it's a new Component, you can create a default MM Component like so:
var newItem = $tcm.createNewItem($const.ItemType.COMPONENT); //or "tcm:16"
newItem.setOrganizationalItem("someFolderId");
newItem.addEventListener("idchange", function() { newItem.checkIn(); }); //Check in the component when it's created
newItem.createFromFile(nameOnServer, nameOnClient, false);
If you need to create a new MM Component with a specific Schema, then it'll be different and you'll need to set Metadata XML, Schema type, etc.
If it's an existing Component, then you don't create it from a file, you set the uploaded MM filename:
var existingItem = $tcm.getItem("someComponentId");
existingItem.addEventListener("load", function(e) {
existingItem.removeEventListener(e.type, arguments.callee); //"load" is called on CheckIn (event below) too, we only want it once!
existingItem.setUploadedMultimediaFilename(nameOnServer);
existingItem.save();
});
existingItem.addEventListener("save", function() { existingItem.checkIn(); });
existingItem.checkOut();
Though again I stress that Events and Core Services may be a better fit, depending on your requirements. In fact, whilst I've attempted to answer you question "How do I upload files to a Multimedia Component?", it may well be that it's better to have an Event on save, or, if it's a GUI extension, to extend the inbuilt functionality rather than trying to recreate it.