I have a JS function within a larger script that updates a progress bar in a web page:
function Funktion(t) {
'use strict';
var value,
max,
go;
go = setInterval(animate, t);
value = 0;
max = 100;
go = 0;
function animate() {
if (value >= max) {
clearInterval(go);
return;
}
value += 1;
document.getElementById('progress').value = value;
document.getElementById('percent').innerHTML = value;
if (value === max) {
clearInterval(go);
}
}
}
Disclaimer: Please assume all relevant variables are properly defined and initialized. The script as a whole functions properly. JSLint complains Unused 'animate'. function animate() {. I've tried suppressing this warning with a combination of /*global go: true */ and /*global animate */. Is there a way to suppress this warning without hacking into the JSLint rules?
Even easier than I initially thought. You just need to define the function before you use it.
/*jslint white:true, browser:true */
function Funktion(t) {
'use strict';
var value,
max,
go;
function animate() {
if (value >= max) {
clearInterval(go);
return;
}
value += 1;
document.getElementById('progress').value = value;
document.getElementById('percent').innerHTML = value;
if (value === max) {
clearInterval(go);
}
}
go = setInterval(animate, t);
value = 0;
max = 100;
go = 0;
}
JSLint is very particular about defining things before they're used. If you call a function you define later in the file, eg, it'll complain.
So you were using animate before JSLint knew what it was. It's very procedural in its evaluation.
So you were using an undefined animate initially, which JSLint probably should have yelled at instead of allowing you to end run around var declaration using a function declaration later.
Then you "re-defined" animate (from JSLint's pov) as a function, and never used it. Har har.
You get a much better error message if you try your code (with a few JSLint directives added) at the more recently updated engine at jslint.com:
'animate' is out of scope.
That error message points at the go = setInterval(animate, t); line, which is more helpful.
Try this one out for unused variables:
/*jshint unused: true, node: true */
Try this one out for unused variables that come as parameters (use this one with the above one):
/*jslint unparam: true, node: true */
Related
How can I read a file in zig, and run over it line by line?
I did found os.File.openRead, but it seems old cause it says that container 'std.os' has no member called 'File'.
std.io.reader.readUntilDelimiterOrEof lets your read any std.io.reader line by line. You usually get the reader of something like a file by calling it’s reader() method. So for example:
var file = try std.fs.cwd().openFile("foo.txt", .{});
defer file.close();
var buf_reader = std.io.bufferedReader(file.reader());
var in_stream = buf_reader.reader();
var buf: [1024]u8 = undefined;
while (try in_stream.readUntilDelimiterOrEof(&buf, '\n')) |line| {
// do something with line...
}
The std.io.bufferedReader isn’t mandatory but recommended for better performance.
I muddled through this by looking at the Zig library source/docs, so this might not be the most idiomatic way:
const std = #import("std");
pub fn main() anyerror!void {
// Get an allocator
var gp = std.heap.GeneralPurposeAllocator(.{ .safety = true }){};
defer _ = gp.deinit();
const allocator = &gp.allocator;
// Get the path
var path_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const path = try std.fs.realpath("./src/main.zig", &path_buffer);
// Open the file
const file = try std.fs.openFileAbsolute(path, .{ .read = true });
defer file.close();
// Read the contents
const buffer_size = 2000;
const file_buffer = try file.readToEndAlloc(allocator, buffer_size);
defer allocator.free(file_buffer);
// Split by "\n" and iterate through the resulting slices of "const []u8"
var iter = std.mem.split(file_buffer, "\n");
var count: usize = 0;
while (iter.next()) |line| : (count += 1) {
std.log.info("{d:>2}: {s}", .{ count, line });
}
}
The above is a little demo program that you should be able to drop into the default project created from zig init-exe, it'll just print out it's own contents, with a line number.
You can also do this without allocators, provided you supply the required buffers.
I'd also recommend checking out this great resource: https://ziglearn.org/chapter-2/#readers-and-writers
Note: I'm currently running a development version of Zig from master (reporting 0.9.0), but I think this has been working for the last few official releases.
To open a file and get a file descriptor back
std.os.open
https://ziglang.org/documentation/0.6.0/std/#std;os.open
To read from the file
std.os.read
https://ziglang.org/documentation/0.6.0/std/#std;os.read
I can't find a .readlines() style function in the zig standard library. You'll have to write your own loop to find the \n characters.
Below is a test case that shows how to create a file, write to it then open the same file and read its content.
const std = #import("std");
const testing = std.testing;
const expect = testing.expect;
test "create a file and then open and read it" {
var tmp_dir = testing.tmpDir(.{}); // This creates a directory under ./zig-cache/tmp/{hash}/test_file
// defer tmp_dir.cleanup(); // commented out this line so, you can see the file after execution finished.
var file1 = try tmp_dir.dir.createFile("test_file", .{ .read = true });
defer file1.close();
const write_buf: []const u8 = "Hello Zig!";
try file1.writeAll(write_buf);
var file2 = try tmp_dir.dir.openFile("test_file", .{});
defer file2.close();
const read_buf = try file2.readToEndAlloc(testing.allocator, 1024);
defer testing.allocator.free(read_buf);
try testing.expect(std.mem.eql(u8, write_buf, read_buf));
}
Check out fs package tests on Github or on your local machine under <zig-install-dir>/lib/fs/test.zig.
Also note that test allocator only works for tests. In your actual source code you need to choose an appropriate allocator.
I'm finding that in MS Edge when I use the debugger; statement or a breakpoint, the scope of this is always the global scope (e.g. the Window object) regardless of what the scope of this is where the code is actually breaking.
For example, the following code is inside a constructor (thus this is not the global object!):
this.myString = "hello";
// returns the current function scope [object Object]
console.log(this);
// returns "hello"
console.log(this.myString);
var fakeThis = this;
/* In this breakpoint, typing:
* `this` returns [object Window]
* `this.myString` returns undefined
* `fakeThis` returns the correct function scope
* `fakeThis.myString` returns "hello".
*/
debugger;
Is this a known bug with the MS Edge console or is there something specific that might be causing this?
Can't reproduce the problem on my side (using Microsoft Edge 44.18362.1.0), it seems that everything works well on my side, the screenshot like this, and the sample code as below:
<p id="demo"></p>
<script>
// Constructor function for Person objects
function Person(first, last, age, eye) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eye;
this.myString = "hello";
// returns the current function scope [object Object]
console.log(this);
// returns "hello"
console.log(this.myString);
var fakeThis = this;
/* In this breakpoint, typing:
* `this` returns [object Window]
* `this.myString` returns undefined
* `fakeThis` returns the correct function scope
* `fakeThis.myString` returns "hello".
*/
console.log(this);
console.log(this.myString);
console.log(fakeThis);
console.log(fakeThis.myString);
debugger;
}
// Create a Person object
var myFather = new Person("John", "Doe", 50, "blue");
// Display age
document.getElementById("demo").innerHTML = "My father is " + myFather.age + ".";
</script>
please try to clear the cache and history, then re-test your code. Also, you could create a new page to test above code, check whether they are working on your side.
I need to update a specific point in the chart when new data arrives. I've written the following function:
function updatePoint(series, x, y) {
for (i = 0; i < series.data.length - 1; i++) {
var point = series.data[i];
if (point.x === x) {
point.update(y);
return;
}
}
}
This works fine, unless the chart has more than turboThreshold points, in which case the series.data is gone, and I only have series.xData and series.yData to work with. I tried the following variant, but the chart does not actually update:
function updateTurboPoint(series, x, y) {
for (i = 0; i < series.xData.length; i++) {
if (series.xData[i] === x) {
if (series.yData.length > i) {
series.yData[i] = y;
return;
}
}
}
}
Setting a breakpoint on the return, I verified that series.yData[i] has the new value, even though it did not appear on the chart. How can I get this to actually update the chart?
I am using HighStock 2.0.4.
EDIT: Created a JSFiddle: http://jsfiddle.net/swish014/2unh1cLa/
EDIT: Changed the title, as I (now) do not believe turbo mode has anything to do with it.
The two comments were key to figuring out my own problem.
It is related to dataGrouping (and not turbo mode as I first thought).
The series.points array does exist, and updating a point there does update the chart as desired.
In my question, I listed two separate functions to update points, but I believe I can use just one function:
function updatePoint(series, x, y) {
for (i = 0; i < series.points.length - 1; i++) {
var point = series.points[i];
if (point.x === x) {
point.update(y);
return;
}
}
}
Is there any way to implement waiting for, say, 3 seconds in ActionScript, but to stay within same function? I have looked setInterval, setTimeOut and similar functions, but what I really need is this:
public function foo(param1, param2, param3) {
//do something here
//wait for 3 seconds
//3 seconds have passed, now do something more
}
In case you wonder why I need this - it is a legal requirement, and no, I can't change it.
Use the Timer to call a function after 3 seconds.
var timer:Timer = new Timer(3000);
timer.addEventListener(TimerEvent.TIMER, callback); // will call callback()
timer.start();
To do this properly, you should create the timer as an instance variable so you can remove the listener and the timer instance when the function is called, to avoid leaks.
class Test {
private var timer:Timer = new Timer(3000);
public function foo(param1:int, param2:int, param3:int):void {
// do something here
timer.addEventListener(TimerEvent.TIMER, fooPartTwo);
timer.start();
}
private function fooPartTwo(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, fooPartTwo);
timer = null;
// 3 seconds have passed, now do something more
}
}
You could also use another function inside your foo function and retain scope, so you don't need to pass variables around.
function foo(param1:int, param2:int, param3:int):void {
var x:int = 2; // you can use variables as you would normally
// do something here
var timer:Timer = new Timer(3000);
var afterWaiting:Function = function(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, afterWaiting);
timer = null;
// 3 seconds have passed, now do something more
// the scope is retained and you can still refer to the variables you
// used earlier
x += 2;
}
timer.addEventListener(TimerEvent.TIMER, afterWaiting);
timer.start();
}
For AS3 use Radu's answer.
For AS2 use the setInterval function like so:
var timer = setInterval(function, 3000, param1, param2);
function (param1, param2) {
// your function here
clearInterval(timer);
}
You can also use delayedCall, from TweenMax. IMHO, it's the sharpest way to do that if you are familiar to TweenMax family.
TweenMax.delayedCall(1, myFunction, ["param1", 2]);
function myFunction(param1:String, param2:Number):void
{
trace("called myFunction and passed params: " + param1 + ", " + param2);
}
In your case, using a anonymous function:
public function foo(param1, param2, param3) {
//do something here
trace("I gonna wait 3 seconds");
TweenMax.delayedCall(3, function()
{
trace("3 seconds have passed");
});
}
why you are doing some confused ways instead of doing the right way?
there is a method named:"setTimeout()";
setTimeout(myFunction,3000);
myFunction is the function you want to call after the period.and 3000 is the period you want to wait(as miliseconds).
you don't need to set then clear interval, or make a timer with one repeat count or do sth else with more trouble☺.
There is no Sleep in ActionScript. But there are other ways to achieve the same thing without having all your code in a single function and wait within that function a specific amount of time.
You can easily have your code in two functions and call the 2nd one after a specific timeout you set in your 1st function.
THIS IS NOT WITHIN ONE FUNCTION - ANSWERS: "How to wait for X seconds in AS2 & 3"
...without using setInterval or clearInterval.
The answers posted above are much faster and easier to use. I posted this here, just in case...
Sometimes you may not be able to use set/clearInterval or other methods based on development restrictions. Here is a way to make a delay happen without using those methods.
AS2 - If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
I have an onEnterFrame countdown timer in here as well, (demos stopping/switching timers).
If you want the delay/glow to be longer - increase the glowGameTime number. Change the names to fit your own needs and/or apply the logic differently.
var startTime:Number = 0;
var currentTime:Number = 0;
var mainTime:Number = 5;//"game" time on enter frame
var glowStartTime:Number = 0;
var glowCurrentTime:Number = 0;
var glowGameTime:Number = 1.8;//"delayed" time on press
btnGlowTest._visible = false;
this.onEnterFrame = TimerFunction;
startTime = getTimer();
function TimerFunction()
{
currentTime = getTimer();
var timeLeft:Number = mainTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up...3 bucks off");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
function glowTimerFunction()
{
glowCurrentTime = getTimer();
var glowTimeLeft:Number = glowGameTime - ((glowCurrentTime - glowStartTime)/1000);
glowTimeLeft = Math.floor(glowTimeLeft);
//trace("glowTimeleft = " + glowTimeLeft);
if(glowTimeLeft <= 0)
{
trace("TIME DELAY COMPLETE!");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
btnTest.onPress = function()
{
trace("onPress");
btnGlowTest._visible = true;
StopTime();
GlowTime();
}
function GlowTime()
{
trace("GlowTime Function");
this.onEnterFrame = glowTimerFunction;
glowStartTime = getTimer();
}
function StopTime()
{
trace(">>--StopTime--<<");
delete this.onEnterFrame;
}
AS3 - Below is the code from above setup to run in AS3. There are different ways to accomplish similar results, yet based on the project scope, these are the methods that were used in order to get things functioning properly.
If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
If you want the delay/glow to be longer - increase the GlowTimer:Timer number, (currently set to 950). Change the names to fit your own needs and/or apply the logic differently.
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
var startTime:Number = 0;
var currentTime:Number = 0;
var gameTime:Number = 4;//"game" time on enter frame
var GlowTimer:Timer = new Timer(950,0);//"delayed" time on press
btnGlowTest.visible = false;
GlowTimer.addEventListener(TimerEvent.TIMER, GlowTimeListener, false, 0, true);
btnTest.addEventListener(MouseEvent.MOUSE_DOWN, btnTestPressed, false, 0, true);
addEventListener(Event.ENTER_FRAME,TimerFunction, false, 0, true);
startTime = getTimer();
function TimerFunction(event:Event)
{
currentTime = getTimer();
var timeLeft:Number = gameTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up, 3 bucks off");
StopTime();
}
}
function GlowTimeListener (e:TimerEvent):void
{
trace("TIME DELAY COMPLETE!");
StopTime();
}
function btnTestPressed(e:MouseEvent)
{
trace("PRESSED");
removeEventListener(Event.ENTER_FRAME, TimerFunction);
btnGlowTest.visible = true;
GlowTimer.start();
}
function StopTime()
{
trace(">>--Stop Time--<<");
btnGlowTest.visible = false;//just for show
btnTest.visible = false;//just for show
GlowTimer.stop();
removeEventListener(TimerEvent.TIMER, GlowTimeListener);
removeEventListener(Event.ENTER_FRAME, TimerFunction);
}
I'm trying to build a streaming .mp3 player to run various sound files on my web site. To do that, I followed a tutorial that includes a code template at:
http://blog.0tutor.com/post.aspx?id=202&title=Mp3%20player%20with%20volume%20slider%20using%20Actionscript%203
However, whether I preserve the template's direction to the author's own sound file or insert my own direction to my online sound file, I keep on running into glitches in the ActionScript that I can't fathom.
Those errors are:
1084: Syntax error: expecting rightparen before _.
1086: Syntax error: expecting semicolon before rightparen.
When I try to correct them, I get new errors. I can't determine whether the sound file is loading; it certainly never plays. The volume slider does not work.
I did find one line that looked like it should have been commented out, the one that reads
to start at the same place
So I tried commenting that out. No dice. Same errors.
Thanks in advance for any suggestions. Code follows:
var musicPiece:Sound = new Sound(new URLRequest _
("http://blog.0tutor.com/JeffWofford_Trouble.mp3"));
var mySoundChannel:SoundChannel;
var isPlaying:Boolean = false;
to start at the same place
var pos:Number = 0;
play_btn.addEventListener(MouseEvent.CLICK, play_);
function play_(event:Event):void {
if (!isPlaying) {
mySoundChannel = musicPiece.play(pos);
isPlaying = true;
}
}
pause_btn.addEventListener(MouseEvent.CLICK, pause_);
function pause_(event:Event):void {
if (isPlaying) {
pos = mySoundChannel.position;
mySoundChannel.stop();
isPlaying = false;
}
}
stop_btn.addEventListener(MouseEvent.CLICK, stop_);
function stop_(event:Event):void {
if (mySoundChannel != null) {
mySoundChannel.stop();
pos = 0;
isPlaying = false;
}
}
var rectangle:Rectangle = new Rectangle(0,0,100,0);
var dragging:Boolean = false;
volume_mc.mySlider_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
function startDragging(event:Event):void {
volume_mc.mySlider_mc.startDrag(false,rectangle);
dragging = true;
volume_mc.mySlider_mc.addEventListener(Event.ENTER_FRAME, adjustVolume);
}
function adjustVolume(event:Event):void {
var myVol:Number = volume_mc.mySlider_mc.x / 100;
var mySoundTransform:SoundTransform = new SoundTransform(myVol);
if (mySoundChannel != null) {
mySoundChannel.soundTransform = mySoundTransform;
}
}
stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function stopDragging(event:Event):void {
if (dragging) {
dragging = false;
volume_mc.mySlider_mc.stopDrag();
}
}
Syntax errors are just what it says they are, the code is not properly written. For instance , you shouldn't have an underscore after URLREquest
var musicPiece:Sound =
new Sound(new URLRequest("http://blog.0tutor.com/JeffWofford_Trouble.mp3"));
to start at the same place should be commented out, simply because it's a comment, it's not a variable or a function.
to call a function "play_" is not really good practice either. Call it soundPlay, if you're concern about conflicts.
same comment for pause_ and stop_