Update linked file in photoshop via java - javascript

I am trying to write a script that will go through every smart object and essentially do the same thing as if I were to open it and then hit the "Layer>Smart Objects> update all modified content". My goal is to create a script that will iterate over every smart object within every smart object; effectively updating all the smart objects recursively.
For example, say I have a single .png that is an image of a pebble. I created a linked smart object out of that, then made some duplicates, then make smart-objects from those, made duplicates of those pebble groups, etc. until I had a mountain. The idea of my script is to iterate through every nested smart object down to that single pebble and update the linked content; so If I change my pebble, I can run the script to then update the entire mountain. Does that make sense?
Here lies my problem though: I am very new to photoshop javascript, and I don't know where to even start with this. ideally I want to loop through the layers, open each smart object found in them, do whatever it takes to update the linked content, then repeat that on all the objects within that object, etc.
i know some c#; and if i was coding this in c# it'd be a foreach loop function that calls itself foreach smart object, like this pseudo code:
void updateeverything(document)
{
foreach(layer OBJ in document)
{
//magic happens on this line to do the same thing as the "update changed content" button in the UI
if(OBJ.type().tostring() == "smartobject")
{
updateeverything(OBJ)
}
}
}

Related

How to make updates in DOM elements more efficient?

I'm making a collaborative browser text editor and I have some optimizations concerns. The goal is to allow users to edit files arbitrarily long. When someone updates the file, everyone receives an update notification, which updates the editor content.
I'm interested to know what happens under the hood with the code bellow: does the program deallocates the old value content and allocates the new one every time this function is called? Ideally, what I would like to do is to have something like a 'file buffer', then I would just move the contents around as the users insert new data into it. But I don't want to lose the convenience of using the textarea element with its events and stuff.
function updateTextAreaValue(new_value) {
var my_textarea = document.querySelector("#my_textarea");
my_textarea.value = new_value;
}
The contents of a textarea are just a string. Setting a new value releases the string it used to contain (making it eligible for garbage collection), and stores the new one.
You've said you don't want to lose the convenience of a textarea element because of its "events and stuff," but a contenteditable div will have the same events, and also a DOM structure within it that you can adjust rather than replacing the entire string. And since it's HTML, it has styling, etc.
But of course, if a textarea serves your needs...

How can I delete a block that contains faulty JavaScript breaking the C5 interface?

I was working on an HTML block in Concrete5 located in the footer. I made a javascript call - can't quite remember it, but I think it was referencing either jQuery or the Google Maps API. Anyway, now the block won't display and oddly enough, I am completely unable to modify/add/remove blocks now. I'm pretty sure it is because of the javascript call it is making, but I can't modify or delete the block to fix the issue.
What am I supposed to now? I tried disabling javascript in my browser but of course that won't let me modify the blocks either.
I don't know 5.8+ that well yet, but this may be unfixable from within the UI.
If the error is in a global area, your best bet might be opening the template, changing the area name where the global area is used and displayed, and recreating it from scratch.
You'd be looking for something like this:
$a = new GlobalArea("Footer Nav");
and change the global area's name, thus creating a new one.
If that's not an option, you may have to resort to deleting (or altering) the faulty block through the API.
In my experience, the easiest way to get a blank page that has C5 bootstrapped is creating a custom Dashboard page:
It's a common task for a Concrete5 developer to create their own Dashboard pages. Dashboard pages are just single pages located inside the "single_pages/dashboard" directory. Once they're added within that location, they automatically show up in the Dashboard.
Now, as to how to edit or delete the block inside the area, I don't have a complete recipe, but this example page showing advanced area operations should get you started.
The API documentation for GlobalAreas is here, for Block here (notice the delete() / deleteBlock() methods.)
FYI although the solution marked as best works, it leaves data in the database that will stay there forever and forces you to change your area's name which might be ok once but not if it happens again and again.
Since that was an HTML block, the best way was to go to your database's interface, probably phpMyAdmin, go into the table "btContentLocal" and do a search for the faulty code you had entered in the HTML block then fix or delete it.
Like that you're back to normal, you don't leave stuff behind, and you can keep your area as it is

Can the DOM be differentially updated?

First and foremost, I've done extensive research about this, under different names that I think could apply such as "Javascript differential templating", "Javascript update DOM without reparsing", "Javascript render UI using deltas" and other variations. Pardon me if I missed an existing thread that covers my question.
Essentially, I would first like to know if most DOM parsers in browsers do the following already, even though I'm fairly sure the answer is no: do they update the DOM differentially (i.e. only the nodes that have changed in the same tree since the last update) when a node is modified? Like I said, I figure the answer is no and they actually reparse and rerender the updated node and everything in its tree.
Which brings me to my question: is there any Javascript library that allows to manage differential updates to a data model and to the DOM?
I realize I might not be really clear about this, so I will provide some code to explain what I mean: http://jsfiddle.net/btZ3e/6/
In that example, I have an "event queue" (which is really a timeline) with events in it. UserEvents all have a unique ID. The way it works now is that UserEvents can execute() and undo(), in the former they modify data in memory (myAppManager.dataModel) and append a <p> in the DOM while in the latter they undo these changes. (Each UserEvent's undo() is defined within the execute() of the same UserEvent as to allow more flexibility, one could consider moving events around independently)
Then, there is myAppManager.render() :
var myAppManager = new function () {
this.dataModel = {
someValue: 0,
disableButton: false
};
this.render = function () {
$('#displaysomevalue').text(this.dataModel.someValue);
$('#go').prop('disabled', this.dataModel.disableButton)
}
}
How would it be possible (is it at all?) that myAppManager.render() only updates what has changed since the last update? I reckon this would mean that I would have to have some sort of differentiation system in my data model too. Ultimately I'm wondering about this because I'm gonna be receiving multiple new UserEvents per second (let's say 20-30 per second at worst?) via websockets and I was wondering if I would need to rerender my whole UI for every new piece of data I get. I investigated into Javascript templates to see how they do it, and it seems they all just go this route:
document.getElementById('someTemplateContainer').innerHTML = someTemplateEngine.getHtmlOutput();
I doubt however they need to refresh as often as I need to in some instances. Is there prior work on this? Did I miss anything? Thank you very much!
The way Backbone.js, as an example, does this is that models (name:value pairs basically) are backed by a view/template, and that models have events associated with them like change. Let's say you have a <ul> where each <li> is one Backbone view, backed by a model.
You could bind every model's change event to re-render its own view (and ONLY its own view). So when the 5th <li> gets its name changed, it will re-render just the contents of that <li>, and the rest of the <ul> is undisturbed.
That lets only new or updated models have their DOM nodes touched and updated.
The difference is that you don't need to know 'what parts of the whole <ul> have changed and just render those', because you've actually decomposed the problem to a series of smaller ones, each of which are responsible for their own rendering and updating logic. (I'm sure other frameworks have similar patterns, and you can do them in vanilla JS too no doubt)

Convert GET Request (HTML string) to a full DOM object

I'm writing a JavaScript script that periodically checks for new elements within a page, that is, DOM tree updates. One of those specific elements contains an hyperlink to other page. My objective is to perform a GET of that page and convert the results to a DOM object in order to trigger a particular event of a particular element within that page. I could do this by var newPage = window.open(hyperlink); and then have access to the elements within the page through newPage.document.getElementById('elementId');. However, the script iterates over many hyperlinks and it is not efficient to open them all up.
So, is there any way to manipulate an object of an entire page efficiently, i.e., without opening it (e.g., $.get(hyperlink, function(page) { // convert page to DOM });)?
Appreciate any answers,
Thanks.
Perhaps you're taking the wrong approach. Rather than convert the page to DOM, you should simply do a regex search for a link. That would clearly be the most efficient way to make use of a page's contents. However, admittedly, it is also a pain to do properly and it doesn't take into consideration links added by javascript.
It depends entirely on what your scope is. If you tell me you're looking for an efficient way of accomplishing this, then I offer this solution. Otherwise, there's no "quick" way of parsing an entire page into DOM no matter which way you slice it.
This will get you started on a regular expression for extracting html links.

Why can't multiple programmatically generated FilteringSelect's share a single store?

Before you ask, a MultiSelect wouldn't really be intuitive for the user in this instance.
I have an object, with an array as its value for 'items', that's provided on the page in a var statement. I also have a function that generates and places dijit.form.FilteringSelects and is triggered on a certain button's click event. Every one of these selects should have the aformentioned object as their 'store' attribute. If I write store: new dojo.data.ItemFileReadStore({ data: object_name }), in my select initialization code, I get weird behavior: I click the generate button 2 times and get 2 FilteringSelects (call them A,B). I click on B's dropdown piece, and the menu appears attached to B. Then I click on A's dropdown button, and menu appears attached to A. If I then go back and click on B's dropdown button again, nothing happens (well not nothing; an error gets thrown).
However, if instead, I have data: {items: array_literal} everything works fine, and I switch back and forth between the 2 as much as I want.
As the data: statement appears once in the javascript code, this isn't a big deal (now that I have a workaround at least). It is however, exceedingly odd. I attempted to dig into the source code, to no avail.Anybody have any idea what's going on here?
The cause is if you passed the data parameter when creating a dojo.data.ItemFileReadStore. The store uses the object directly. In the source code, you can see this._arrayOfTopLevelItems = dataObject.items;. So the two stores you created used the same array object as the back-end storage. So a change you made in one widget also changed the other widget. By using array literals, you actually created two distinct objects, then it should be fine. Two widgets will not interfere with each other.
My solution to this case is to use dojo.clone to create a copy of the data, then use the copy to create the store.

Categories

Resources