Perpetual counter within the same web session - session

Trying to have a counter on a web page that does not restart on each different page view within the same user session. Currently using this code (thanks to Praveen Kumar Purushothaman) but this counter resets every time a different page is viewed.
setTimeout(start, 0);
var i = 0;
var num = document.getElementById("number");
function start() {
increase();
setInterval(increase, 1000);
}
function increase() {
if (i < 100000) {
i += 10.41;
num.innerText = i.toFixed(2);
}
}
<span id="number"></span>

My suggestion is storing the variable into session storage. I have added more details in the comments:
setTimeout(start, 0);
// You're saving your current value here.
// Let's use localStorage. Set the i value if it doesn't exist for the first time.
if (!localStorage.getItem("i")) {
localStorage.setItem("i", 0);
}
var num = document.getElementById("number");
function start() {
increase();
setInterval(increase, 1000);
}
function increase() {
var i = localStorage.getItem("i");
if (i < 100000) {
i += 10.41;
// When you're making any changes, make changes to the localStorage too.
localStorage.setItem("i", i);
num.innerText = i.toFixed(2);
}
}

Related

Photoshop CC2019 auto-update all linked smart objects including nested ones

I have Photoshop CC2019 PSD document containing several smart objects that contains other smart objects that contains other smart objects. Some of these have linked layers. Normally, such images are not updated automatically (which is extremely annoying, Adobe!) but you have to manually update each of them once the linked image content has changed.
There is a .jsx script file named "Update All Modified Content.jsx" which auto-updates linked layers (PNG image in my case) but only if the smart object is in the top most document - that is no nested smart objects with linked layers are updated automatically.
My question is: does anyone know how to update the content of the above mentioned .jsx file so that it would auto-update all linked images across all the smart objects in PSD document including nested ones?
For those who care or would be willing to help updating the code here it is:
// Update all modified content
var idplacedLayerUpdateAllModified = stringIDToTypeID( "placedLayerUpdateAllModified" );
executeAction( idplacedLayerUpdateAllModified, undefined, DialogModes.NO );
So, after spending half a day with it I finally solved it myself. Here is the code:
#target photoshop
// SET INITIAL ACTIVE DOCUMENT
var mainDocument = app.activeDocument;
// SAVE THE DOCUMENT NAME FOR FUTURE USE
var mainDocName = mainDocument.name;
// RUN THE MAIN UPDATE FUNCTION
mainDocument.suspendHistory("processAllSmartObjects", "autoupdateAllSmartObjects(mainDocument, 0)");
// FINALLY SAVE THE MAIN DOCUMENT
mainDocument.save();
function autoupdateAllSmartObjects(theParent, prevVal) {
// FUNCTION TO TEST IF SMARTOBJECT IS LINKED
function isLinkedSO(obj) {
var localFilePath = "";
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID('Lyr '), obj.id);
var desc = executeActionGet(ref);
var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));
var isLinked = false;
// TEST IF IT HAS LINKED FILE
try {
var localFilePath = smObj.getPath(stringIDToTypeID('link'));
isLinked = true;
} catch(e) {
//
}
return isLinked;
}
// FUNCTION TO UPDATE LINKED SMART OBJECT
function doTheUpdate(LYR, stackNr) {
// SET ACTIVE LAYER TO ACTUALY ITERATED ONE
app.activeDocument.activeLayer = LYR;
// RUN IN "SILENT" MODE
app.displayDialogs = DialogModes.NO;
var layer = app.activeDocument.activeLayer;
// IF ACTIVE LAYER IS SMARTOBJECT
if (layer.kind == "LayerKind.SMARTOBJECT") {
//alert(layer);
// OPEN THE SMARTOBJECT
app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
// DO THE ACTUAL FILE UPDATE
var idplacedLayerUpdateAllModified = stringIDToTypeID( "placedLayerUpdateAllModified" );
executeAction( idplacedLayerUpdateAllModified, undefined, DialogModes.NO);
// IF IT IS NOT THE "CORE/MAIN" DOCUMENT
if(stackNr > 0) {
// SAVE CHANGES (UPDATE) AND CLOSE IT
app.activeDocument.close(SaveOptions.SAVECHANGES);
}
// CONTINUE INSIDE THIS ACTIVE SMARTOBJECT
autoupdateAllSmartObjects(app.activeDocument, stackNr);
}
return;
}
// FUNCTION TO PARSE GROUPS
function parseGroup(LYR) {
var groupLayers = LYR.layers;
// IF GROUP IS NOT EMPTY
if(groupLayers.length > 0) {
// PARSE ALL LAYERS IN THE GROUP
for (var i = groupLayers.length - 1; i >= 0; i--) {
var lyr = groupLayers[i];
// IF NOT LOCKED = NOT EDITABL:E
if(!lyr.allLocked) {
// YET ANOTHER GROUP?
if (lyr.typename == "LayerSet") {
// IF IT IS NOT EMPTY
if (lyr.layers.length > 0) {
// RE-RUN THE SCRIPT ANEW WITH THE SELECTED GROUP AS LAYERS SOURCE
autoupdateAllSmartObjects(lyr, 0);
}
// LAYERS
} else if (lyr.typename == "ArtLayer") {
// IF THE LAYER IS SMARTOBJECT
if (lyr.kind == LayerKind.SMARTOBJECT) {
// IF THE LAYER IS SET TO "visible" (THAT IS: NOT DISABLED)
if(lyr.visible){
// TEST IF THE SMARTOBJECT IS ACTUALLY LINKED
if(!isLinkedSO(lyr)) {
// RUN THE UPDATE SUB-FUNCTION
doTheUpdate(lyr, i);
}
}
}
}
}
}
}
}
// PARSE ALL THE LAYERS
for (var i = theParent.layers.length - 1 - prevVal; i >= 0; i--) {
var theLayer = theParent.layers[i];
// ONLY ArtLayers
if (theLayer.typename == "ArtLayer") {
// IF THE LAYER IS SMARTOBJECT
if (theLayer.kind == LayerKind.SMARTOBJECT) {
// IF THE LAYER IS SET TO "visible" (THAT IS: NOT DISABLED)
if(theLayer.visible){
// TEST IF THE SMARTOBJECT IS ACTUALLY LINKED
if(!isLinkedSO(theLayer)){
// RUN THE UPDATE SUB-FUNCTION
doTheUpdate(theLayer, i);
// IF WE ARE AT THE LAST LAYER IN THE STACK AND IT IS NOT OUR MAIN DOCUMENT
if(i == 0 && app.activeDocument.name !== mainDocName) {
// SAVE CHANGES (UPDATE) AND CLOSE IT
app.activeDocument.close(SaveOptions.SAVECHANGES);
}
}
}
}
// ONLY Groups
} else if (theLayer.typename == "LayerSet") {
// RUN SUB-FUNCTION FOR GROUP PARSING
parseGroup(theLayer);
// ANYTHING ELSE
} else {
autoupdateAllSmartObjects(theLayer, m);
}
}
return;
};
OP's script works!! It was going in loops for me too but after some trial and error, I realised that my smart objects (SO) that are linked across artboards ( - e.g. if you change one SO, it changes on various artboards) - were the issue. I hid all such SO and it works.
so basically, it only works for Smart Objects + copies made via 'New smart object via copy' NOT 'duplicate layer' / copypaste smart objects. If your work contains a 'duplicate layer' SO - it will break the script. You need to hide these objects ( or not work like that all together) before running the script

Transitioning from Session to ReactiveVar or ReactiveDict (Meteor)

So, I'm making an audio player and I've got a bit of code to get the audio duration of the selected file, for the timer. It was working really well with Session, but then, as I might want more than one player per page, I decided to switch to ReactiveVar or ReactiveDict and I don't think I quite grasped how they work, because my code broke. Can you help me? What am I doing wrong?
This is the code as it was with Session.
Template.audioplayer.onRendered(
function() {
audio = $("audio").get(0);
}
);
Template.audioplayer.helpers({
audioduration: function() {
if (!Session.get("audioduration")) {
audioLenght = Meteor.setInterval(function() {
var totaltime = parseInt(audio.duration, 10);
var mins = Math.floor(audio.duration / 60, 10);
var secs = totaltime - mins * 60;
var gimmethetime = mins + ':' + (secs > 9 ? secs : '0' + secs);
Session.set("audioduration", gimmethetime);
return Session.get("audioduration");
}, 500);
} else {
Meteor.clearInterval(audioLenght);
return Session.get("audioduration");
}
}
});
This is my latest attempt at the same result with ReactiveVar. It came out with "TypeError: Cannot read property 'get' of undefined".
Template.audioplayer.onCreated(
function() {
audio = $("audio").get(0);
this.audioduration = new ReactiveVar();
}
);
Template.audioplayer.helpers({
audioduration: function() {
if (!Template.audioduration.get()) {
audioLenght = Meteor.setInterval(function() {
var totaltime = parseInt(audio.duration, 10);
var mins = Math.floor(audio.duration / 60, 10);
var secs = totaltime - mins * 60;
var gimmethetime = mins + ':' + (secs > 9 ? secs : '0' + secs);
Template.instance().audioduration.set(gimmethetime);
return gimmethetime;
}, 500);
} else {
Meteor.clearInterval(audioLenght);
return Template.instance().audioduration.get();
}
}
});
Thanks in advance!
I would add some information before answering your question. I have seen a lot of resources over the Internet using the Session variable to store temporary data and this stunned me a little. You must understand that the Session lifecycle start when you load the page and ends when you reload the page or close your browser. Let's say you store all your temporary data inside the session, if I take time to got through all the application then my session will be polute with data from all these pages. You are not faulty I just wanted to add some information on this. Anyone correct me if I'm wrong.
Now comes the place to answer.
In your helper, you have a test. In this test you try to access the reactiveVar with Template.audioduration. But as you have made for all the other calls it should be Template.instance().audioduration.get()
Template.audioplayer.onCreated(
function() {
audio = $("audio").get(0);
this.audioduration = new ReactiveVar();
}
);
Template.audioplayer.helpers({
audioduration: function() {
if (!Template.instance().audioduration.get()) {
audioLenght = Meteor.setInterval(function() {
var totaltime = parseInt(audio.duration, 10);
var mins = Math.floor(audio.duration / 60, 10);
var secs = totaltime - mins * 60;
var gimmethetime = mins + ':' + (secs > 9 ? secs : '0' + secs);
Template.instance().audioduration.set(gimmethetime);
return gimmethetime;
}, 500);
} else {
Meteor.clearInterval(audioLenght);
return Template.instance().audioduration.get();
}
}
});
Like this it should work...
EDIT :
You had a second error, I put it here for later reference and explanation.
"Exception in setInterval callback: TypeError: Cannot read property 'audioduration' of null". In order to correct it, I told you to create a variable in the helper scope with Template.instance().
This is a typical JS error. In JS, all the diffulty is to understand what is the scope of a function. In this case, it is possible to access the Template variable in the helper but it cannot be accessed inside the callback. If you reference the template instance inside the context of the helper then it can be accessed from the callback. I don't know much about how are linked the different contexts in this particular case. But it is quite usual that the this object cannot be accessed by callbacks, we are forced to user var that = this;. `See this post.

In UnityScript, why does GUI not get called within hit on collider?

I'm trying to print out text when a user touches a sprite, however, even though I get no errors when building and running the code, the code refuses to printout the text and I cannot understand what I am doing wrong. Please help me understand why it does not print.
It prints the debug text when I touch the sprite, but not the GUI text with total.
This is the code:
#pragma strict
function Start () {
OnGUI();
}
function OnGUI(){
//var total = 0;
//GUI.Label( myRect, total.ToString() ); // Displays "10".
//GUI.Label( myRect, "" + bullets ); // Displays "10".
// GUI.Label(Rect(0,0,Screen.width,Screen.height),"Total:"+total);
}
//function Update () {
//}
var platform : RuntimePlatform = Application.platform;
function Update(){
if(platform == RuntimePlatform.Android || platform == RuntimePlatform.IPhonePlayer){
if(Input.touchCount > 0) {
if(Input.GetTouch(0).phase == TouchPhase.Began){
checkTouch(Input.GetTouch(0).position);
}
}
}else if(platform == RuntimePlatform.WindowsEditor){
if(Input.GetMouseButtonDown(0)) {
checkTouch(Input.mousePosition);
}
}
}
function checkTouch(pos){
var total = 0;
var wp : Vector3 = Camera.main.ScreenToWorldPoint(pos);
var touchPos : Vector2 = new Vector2(wp.x, wp.y);
var hit = Physics2D.OverlapPoint(touchPos);
if(hit){
GUI.Label(Rect(0,0,Screen.width,Screen.height),"Total:");
Debug.Log(hit.transform.gameObject.name);
hit.transform.gameObject.SendMessage('Clicked',0,SendMessageOptions.DontRequireReceiver);
//total = total +1;
}
}
You cannot put a gui item outside the OnGUI Method. You need to set a boolean to turn on the label.
Something along these lines.
OnGUI(){
if(labelbool)
GUI.Label ....
}
check(){
labelbool = true;
}

Less CSS and local storage issue

I'm using LESS CSS (more exactly less.js) which seems to exploit LocalStorage under the hood. I had never seen such an error like this before while running my app locally, but now I get "Persistent storage maximum size reached" at every page display, just above the link the unique .less file of my app.
This only happens with Firefox 12.0 so far.
Is there any way to solve this?
P.S.: mainly inspired by Calculating usage of localStorage space, this is what I ended up doing (this is based on Prototype and depends on a custom trivial Logger class, but this should be easily adapted in your context):
"use strict";
var LocalStorageChecker = Class.create({
testDummyKey: "__DUMMY_DATA_KEY__",
maxIterations: 100,
logger: new Logger("LocalStorageChecker"),
analyzeStorage: function() {
var result = false;
if (Modernizr.localstorage && this._isLimitReached()) {
this._clear();
}
return result;
},
_isLimitReached: function() {
var localStorage = window.localStorage;
var count = 0;
var limitIsReached = false;
do {
try {
var previousEntry = localStorage.getItem(this.testDummyKey);
var entry = (previousEntry == null ? "" : previousEntry) + "m";
localStorage.setItem(this.testDummyKey, entry);
}
catch(e) {
this.logger.debug("Limit exceeded after " + count + " iteration(s)");
limitIsReached = true;
}
}
while(!limitIsReached && count++ < this.maxIterations);
localStorage.removeItem(this.testDummyKey);
return limitIsReached;
},
_clear: function() {
try {
var localStorage = window.localStorage;
localStorage.clear();
this.logger.debug("Storage clear successfully performed");
}
catch(e) {
this.logger.error("An error occurred during storage clear: ");
this.logger.error(e);
}
}
});
document.observe("dom:loaded",function() {
var checker = new LocalStorageChecker();
checker.analyzeStorage();
});
P.P.S.: I didn't measure the performance impact on the UI yet, but a decorator could be created and perform the storage test only every X minutes (with the last timestamp of execution in the local storage for instance).
Here is a good resource for the error you are running into.
http://www.sitepoint.com/building-web-pages-with-local-storage/#fbid=5fFWRXrnKjZ
Gives some insight that localstorage only has so much room and you can max it out in each browser. Look into removing some data from localstorage to resolve your problem.
Less.js persistently caches content that is #imported. You can use this script to clear content that is cached. Using the script below you can call the function destroyLessCache('/path/to/css/') and it will clear your localStorage of css files that have been cached.
function destroyLessCache(pathToCss) { // e.g. '/css/' or '/stylesheets/'
if (!window.localStorage || !less || less.env !== 'development') {
return;
}
var host = window.location.host;
var protocol = window.location.protocol;
var keyPrefix = protocol + '//' + host + pathToCss;
for (var key in window.localStorage) {
if (key.indexOf(keyPrefix) === 0) {
delete window.localStorage[key];
}
}
}

Flash AS2 show text one by one from array

I want to dynamically display some text from an array one after another in a dynamic textfield.
var wordList:Array = new Array('one','two','three');
for (var i = 0; i < wordList.length; i++) {
this.text_mc.txt.text = wordlist[i];
// Pause for 3 seconds and then move next
}
its the "Pause for 3 seconds and then move next" part I cant figure out.
Thanks.
track what index of the array you are currently showing, and use the setInterval function to call your 'showNext' function every 3000 milliseconds
ie)
var wordList:Array = new Array('one','two','three');
var curIndex = 0;
renderText(curIndex);
setInterval( showNextText, 3000 );
function showNextText()
{
curIndex++;
renderText(curIndex);
}
function renderText( index:Number )
{
this.text_mc.txt.text = wordlist[index];
}

Resources