What I'm trying to achieve:
Change state when the user clicks previous or next, each state is assigned an id and will need to figure out which id is previous or next before changing previous or next state.
Current Problem:
I have managed to display the current state id '1' and I have managed to group all the other id's within an array but I don't know how to get the next and previous buttons to trigger the right previous or next states on click.
Please find my code below, I've added comments/notes to point things out.
Any help/advice would be helpful! Thank you.
Controller JS
// -- Current Page ID, '1' -- //
var currentID = $stateParams.id;
// -- Body Type, 'triangle' -- //
var bodyType = $scope.$storage.userData.bodyType.bodyType;
// -- Dress Array, [{"id": "1", "bodyType": "triangle"},{"id": "2", "bodyType": "triangle"},{"id": "3", "bodyType": "round"},{"id": "4", "bodyType": "triangle"}] --//
var dressArray = $scope.$storage.appData.dresses;
// -- Remove anything that doesn't match the current body Type e.g Remove 'round' -- //
var removeRound = $filter('filter')(dressArray, function(value, index) {return value.bodyType == bodyType;});
// -- Dress Array -- //
$scope.dressArray = [];
// -- Push each filter value to Array, ["1", "2", "4"] -- //
angular.forEach(removeRound, function(value, key) {
$scope.dressArray.push(value.id);
});
// -- Console Test, ["1", "2", "4"] -- //
console.log($scope.dressArray);
// -- If currentID = '1', The next button should display '2' -- //
// -- If currentID = '2', The next button should display '4'--//
$scope.nextDress = function() {
$state.go('main.rail', {id: idhere });
};
// -- If currentID = '1', The previous button should display '4' -- //
// -- If currentID = '2', The previous button should display '1' -- //
$scope.previousDress = function() {
$state.go('main.rail', {id: idhere });
};
HTML
<li class="next"><md-button ng-click="nextDress()">Next</md-button></li>
<li class="previous"><md-button ng-click="previousDress()">Previous</md-button></li>
check that the currentId + 1 is not greater than the length of the array for the next item (if greater, go to the first) and check that the currentId - 1 is not less than 0, if yes, go to the last item (to make it cyclic):
$scope.nextDress = function() {
var next = parseInt(currentId) + 1 > dressArray.length ? 0 : parseInt(currentId) + 1;
$state.go('main.rail', {id: next });
};
$scope.previousDress = function() {
var prev = parseInt(currentId) - 1 < 0 ? dressArray.length - 1 : parseInt(currentId) - 1;
$state.go('main.rail', {id: prev });
};
I would make the data like a closed linked list, run this every time after passing through filter.
var currentItem; // keep a reference of current item
var arrayToLL = function(arr){
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
if (i == 0) item.prev = arr[arr.length - 1];
else item.prev = arr[i - 1];
if (i == arr.length - 1) item.next = arr[0];
else item.next = arr[i + 1];
if (item.id == currentId) { // you may get currentId from $stateParams
currentItem = item;
}
}
}
$scope.nextDress = function() {
$state.go('main.rail', {id: currentItem.next.id });
};
$scope.previousDress = function() {
$state.go('main.rail', {id: currentItem.prev.id });
};
Related
So im trying to automaically retrieve a random entry from an array listed in a seperate node.js file
function code
var replies = require('./replies');
function followed(event) {
var name = event.source.name;
var flname = event.source.screen_name;
var myArray = [replies];
var item = myArray[(Math.random()*myArray.length)|0];
var followtweet = '#' + flname + item;
if(flname != "UserName") {
tweetIt(followtweet);
console.log('\n#' + flname + ' Followed You');
console.log('\nYou Tweeted:\n ' + followtweet);
} else {
console.log(' Interferance From Another Bot! \n');
}
}
External Array
module.exports = {
followedone: 'one',
followedtwo: 'two',
followedthre: 'three',
replyone: ' one',
replytwo: ' two',
replythre: ' three',
}
When I Run This and the function runs i get this
#LandscapesLucid Followed You
You Tweeted:
#LandscapesLucid[object Object]
Waiting For The Next Action
I'm not sure why its only showing the [object Object] instead of either one two or three like in the array
Can you try to change from this
var item = myArray[(Math.random()*myArray.length)|0];
to this?
var item = myArray[Math.floor(Math.random()*items.length)];
I am trying to to update the attribute of an onbject in angularjs array of object.
I have the folowing array of object:
$scope.formes= [
{id: 0, geo: 0,cx:0, cy:0, b:0, h:0, r:0, d:0, a:0, ax:0, ay:0, val: 0}
];
The values of each attribute are set to 0 by default until the user type in a new value in a field. Some values are updated after the user add a new objet or hit a button. This app is used to calculate the center of basic geometric shapes and there moments. Just fyi.
This is the function that is running when the user add an object.
$scope.ajoutForme = function(){
$scope.formes.a = parseInt($scope.formes.b) * parseInt($scope.formes.h); /// not working
$scope.formes.push({
id: $scope.nbrForme++ //just adding and new id
});
}
Before I add the objet I want to update some values with calculations. For exemple in this case I what to set the value of a with b*h.
I have try
$scope.formes[nbrForme].h = parseInt($scope.formes[nbrForme].b) * parseInt($scope.formes[nbrForme].h); //This is working but only the first time I press the button??
nbrForme is = to the id of the element I am working on and gets incremented when I add a new object.
Complete Controler
var moment = angular.module('moment',[]);
var nbrForme = 0;
moment.controller('momentCtrl', ['$scope', function($scope) {
$scope.nbrForme = nbrForme;
$scope.formes= [
{id: 0, geo: 0,cx:0, cy:0, b:0, h:0, r:0, d:0, a:0, ax:0, ay:0, val: 0}
];
$scope.ajoutForme = function(){
$scope.formes[nbrForme].a = parseInt($scope.formes[nbrForme].b) * parseInt($scope.formes[nbrForme].h); /// only work once
$scope.formes.push({
id: $scope.nbrForme++
});
}
}
}]);
Your object definition is wrong:
$scope.object = [
{id:0, attr1:2, attr2:4, attr3:0},
{id:1, attr1:2, attr2:4, attr3:0},
{id:2, attr1:2, attr2:4, attr3:0}
];
Note a added , to separate the elements of the array.
Edit:
You wrote that this line doesn't work $scope.formes.a = parseInt($scope.formes.b) * parseInt($scope.formes.h);
This is because $scope.formes is an array, so you must reference to a specific object inside the array that has the a/b/h property. The question is which one?
If it's the first index in the array you'll do
$scope.formes[0].a = parseInt($scope.formes[0].b) * parseInt($scope.formes[0].h);
The last element:
var lastIndex = $scope.formes.length - 1;
if (lastIndex >= 0) {
$scope.formes[lastIndex].a = parseInt($scope.formes[lastIndex].b) * parseInt($scope.formes[lastIndex].h);
}
If $scope.nbrForme is the ID of the element you're currently working on, then you need to decrease its value by 1, because you start with the value of 1, and the first index of an array is 0:
$scope.formes[$scope.nbrForme - 1].a = parseInt($scope.formes[$scope.nbrForme - 1].b) * parseInt($scope.formes[$scope.nbrForme - 1].h);
I'm trying to figure out how to watch an array and update an object, like this.
var vm = this; //controller
vm.order = {
totalValue: 25,
products: [{id:0, val: 10, qtd: 1}, {id:1, val: 15, qtd: 1}]
};
If I push a new product into this order object, how do I update the totalValue just watching the collection ? (totalValue = All Val * All Qtd)
It is necessary because the "qtd" field is bind to an input field, so I can change the value of all "products" at any time.
UPDATE
$scope.$watchCollection(
function() { return self.order.products; },
function(products) {
self.order.totalValue = products.reduce(function (p, n) {
console.log(n.qtd);
console.log(n.val);
return p + n.qtd * n.val;
}, 0);
});
The code worked, but only when I push a new "product" into order.
I have to watch every order.products.product.qtd and change the order.totalValue every time the user change the qtd of a product
Try this way:
$scope.$watch('order.products', function (products) {
scope.order.totalValue = products.reduce(function (p, n) {
return p + n.qtd * n.val;
}, 0);
}, true);
This will deep watch array to detect qtd and val changes inside array items.
I have this code in my simple flash. I want to save name and score in my quiz. My code reference in this website http://www.mollyjameson.com/blog/local-flash-game-leaderboard-tutorial/
I want to make my code in just one actionscript. But I didn't success do it.
var m_FlashCookie = SharedObject.getLocal("LeaderboardExample");
var EntryName:String ="nama kamu";
var EntryScore:String ="nilai";
const NUM_SCORES_SAVED:int = 10;
inputBoxScore.text = EntryScore;
inputBoxName.text = EntryName
var latest_score_object:Object = {
name: EntryName,
score: EntryScore
};
var arr:Array;
arr = m_FlashCookie.data.storedArray
if ( arr == null)
{
arr = new Array();
}
arr.push( latest_score_object );
arr.sortOn("score", Array.NUMERIC | Array.DESCENDING);
if ( arr.length < NUM_SCORES_SAVED )
{
arr.pop();
}
btnSave.addEventListener(MouseEvent.CLICK, saveData);
function saveData(event:Event):void
{
m_FlashCookie.data.arr = arr;
m_FlashCookie.flush();
}
var myHTMLL:String = "";
var total_stored_scores:int = arr.length;
btnLoad.addEventListener(MouseEvent.CLICK, loadData);
function loadData(event:Event):void
{
for (var i:int = 0; i < total_stored_scores; ++i)
{
// loop through every entry, every entry has a "name" and "score" field as that's what we save.
var leaderboard_entry:Object = arr[i];
// is this the last score that was just entered last gamestate?
if ( leaderboard_entry == latest_score_object )
{
myHTMLL += (i+1) + ". <b><font color=\"#0002E5\">"+ leaderboard_entry.name + " " + leaderboard_entry.score +"</font></b><br>";
}
else
{
myHTMLL += (i+1) + ". "+ leaderboard_entry.name + " " + leaderboard_entry.score +"<br>";
}
}
myHTML.text = myHTMLL;
}
Can anybody help me?
You're saving the array as data.arr but reading the array as data.storedArray. You need to make them the same.
In other words, you've written this:
m_FlashCookie.data.arr = arr;
And when you load:
arr = m_FlashCookie.data.storedArray;
This clearly doesn't make sense: data.storedArray is never set, so it will never have a value, so you will always end up with a new empty array.
You need to use the same property on the shared object data. For example:
m_FlashCookie.data.storedArray = arr;
m_FlashCookie.flush();
Looking at your code, there's a number of other issues:
The latest score is immediately removed because arr.length < NUM_SAVED_SCORES is going to be true from the start, since arr starts out empty, and it then calls arr.pop() which will remove the latest entry that was just added. So the array is always empty.
It adds the score immediately with arr.push(latest_score_object) instead of waiting until the user clicks save, so the value of the input texts don't matter at all -- the saved values will always be "nama kamu" and "nilai".
The following fixes all the issues mentioned:
var leaderboard = SharedObject.getLocal("leaderboard");
const MAX_SAVED_SCORES:int = 10;
inputBoxName.text = "nama kamu";
inputBoxScore.text = "nilai";
var entries:Array = leaderboard.data.entries || [];
var latestEntry:Object;
displayScores();
btnLoad.addEventListener(MouseEvent.CLICK, loadClick);
btnSave.addEventListener(MouseEvent.CLICK, saveClick);
function loadClick(e:MouseEvent):void {
displayScores();
}
function saveClick(e:MouseEvent):void {
saveLatestScore();
displayScores();
}
function saveLatestScore():void {
// create the latest entry based on input texts
latestEntry = {
name: inputBoxName.text,
score: inputBoxScore.text
};
// add the entry and sort by score, highest to lowest
entries.push(latestEntry);
entries.sortOn("score", Array.NUMERIC | Array.DESCENDING);
// if reached the limit, remove lowest score
if (entries.length > MAX_SAVED_SCORES) {
entries.pop();
}
// store new sorted entries to shared object
leaderboard.data.entries = entries;
leaderboard.flush();
}
function displayScores():void {
var myHTMLL:String = "";
for (var i:int = 0; i < entries.length; ++i) {
// loop through every entry, every entry has a "name" and "score" field as that's what we save.
var entry:Object = entries[i];
// is this the last score that was just entered last gamestate?
if (entry == latestEntry)
myHTMLL += (i+1) + ". <b><font color=\"#0002E5\">"+ entry.name + " " + entry.score +"</font></b><br/>";
else
myHTMLL += (i+1) + ". "+ entry.name + " " + entry.score +"<br/>";
}
myHTML.htmlText = myHTMLL;
}
Hello and thank you for your time. I have an as3 code which randomly picks 5 frames out of 7, no repeats.
var mygroup1:RadioButtonGroup = new RadioButtonGroup("group1");
q1a1.group = q1a2.group = q1a3.group = q1a4.group = q1a5.group = mygroup1;
var number_array:Array = [8158,8159,8160,8161,8162,8163,8164];
var final_array:Array = [];
var count_selected:int = 5;
var i:int;
for(i = 0; i < count_selected; i++)
{
if(number_array.length == 0)
break;
else
final_array.push(number_array.splice(Math.floor(Math.random() * number_array.length), 1)[0]);
}
var index = 0;
var currentQuestion:int = final_array[index];
var answers:Object = {
8158: 'B) 12',
8159: 'F) All of the above',
8160: 'A) True',
8161: 'B) False',
8162: 'C) 4',
8163: 'F) D and E',
8164: 'B) B'
};
var getAnswer = mygroup1.selection.label; //Getting the selection from RadioButtonGroup
submitBtn.addEventListener(MouseEvent.CLICK, onSubmitClicked);
function onSubmitClicked(e:MouseEvent):void {
var answer:String = getAnswer();
if (answer === answers[currentQuestion])
awardScore(currentQuestion);
++index;
currentQuestion = final_array[index];
gotoAndStop(final_array[index]);
}
and when you click on the "startBtn", it takes you to the first randomly generated frame(final_array[0]) and it's all great to start the process randomly.
Each of the next 7 frames has a submit button(b1,b2...b7) which keeps track of the score and submits the answer and also should go to the next randomly picked frame but only 5 times, following the remaining generated frames....gotoAndStop(final_array[1])...(final_array[2])....(final_array[3])....(final_array[4]).
b1.addEventListener(MouseEvent.CLICK, quizHandler1)
function quizHandler1(event:MouseEvent):void{
if(mygroup1.selection.label=="B) 12") {
count = count + 20;
scoreresult.text = (count).toString();
gotoAndStop(final_array[1]);
}
else{
gotoAndStop(final_array[1]);
}
}
My problem is...Since the user will only go to 5 randomly picked frames out of 7, how can I make sure all the buttons in all 7 frames will listen and follow the gotoAndStop(final_array[]); statement in the order of 5? Because at the end, 2 frames will be left out, and those two frames will change randomly in every roll. I hope I could explain my dilemma. Thank you again.
To do a quiz like yours, I think that you don't need to duplicate all content on every frame. You can put your questions in MovieClips ( or one MovieClip with many frames ) and then you can add it to your stage, and for your check box you can create it once and every time you can change just their values and labels. For buttons, you need only one button which will validate and check the current question and the go to the next one.
Take a look on this example :
var score:int;
var max_score:int;
const default_score:int = 20;
// create our questions list (7 questions) :
var questions_list:Object = {
// index : to identify our question
// movie_clip : the class name used for AS linkage
1: { index : 1, movie_clip : Question1, good_answer : 'css3', first_answer : 'html5', second_answer : 'jquery', third_answer : 'css3', score : default_score },
2: { index : 2, movie_clip : Question2, good_answer : 'html5', first_answer : 'html5', second_answer : 'less', third_answer : 'ruby', score : 50 },
3: { index : 3, movie_clip : Question3, good_answer : 'jquery', first_answer : 'ruby', second_answer : 'jquery', third_answer : 'css3', score : default_score },
4: { index : 4, movie_clip : Question4, good_answer : 'less', first_answer : 'less', second_answer : 'html5', third_answer : 'css3', score : 15 },
5: { index : 5, movie_clip : Question5, good_answer : 'nodejs', first_answer : 'python', second_answer : 'nodejs', third_answer : 'jquery', score : 10 },
6: { index : 6, movie_clip : Question6, good_answer : 'python', first_answer : 'css3', second_answer : 'html5', third_answer : 'python', score : default_score },
7: { index : 7, movie_clip : Question7, good_answer : 'ruby', first_answer : 'ruby', second_answer : 'html5', third_answer : 'less', score : default_score }
};
var enabled_questions:Array = [1, 2, 3, 4, 5, 6, 7];
var current_question:int = 0;
//----------------------------------------------------------------------------------------------------
// sprite that shows our questions
var questions_container:Sprite = new Sprite();
questions_container.x = questions_container.y = 20;
questions_container.visible = false;
addChild(questions_container);
var checks_group:RadioButtonGroup = new RadioButtonGroup('checks_group');
// sprite that contains our 3 check box
var checks_container:Sprite = new Sprite();
checks_container.visible = false;
checks_container.x = int(stage.stageWidth / 2);
checks_container.y = 50;
addChild(checks_container);
// create our check box, 3 buttons in my case
// the 4th one is used only to uncheck every time all check box
for(var i:int = 0; i < 4; i++)
{
var btn_check:RadioButton = new RadioButton();
if(i != 3){
btn_check.y = i * 30;
} else {
// our 4th check box is hidden
btn_check.visible = false;
}
btn_check.group = checks_group;
btn_check.name = 'btn_check' + i;
checks_container.addChild(btn_check);
}
// start button
var btn_start:Button = new Button();
btn_start.label = 'Start ! ';
btn_start.width = 180;
btn_start.height = 60;
btn_start.x = int((stage.stageWidth - btn_start.width)/2);
btn_start.y = int((stage.stageHeight - btn_start.height)/2) - 20;
btn_start.addEventListener(MouseEvent.CLICK, startQuiz);
addChild(btn_start);
// next button, to go to the next question
var btn_next:Button = new Button()
btn_next.label = 'Next >> ';
btn_next.width = 90;
btn_next.height = 30;
btn_next.visible = false;
btn_next.x = stage.stageWidth - btn_next.width - 10;
btn_next.y = stage.stageHeight - btn_next.height - 10;
btn_next.addEventListener(MouseEvent.CLICK, checkAnswer);
addChild(btn_next);
// a text field which will show the score and the current question number
var txt_score:TextField = new TextField();
txt_score.width = 200;
txt_score.height = 30;
txt_score.x = stage.stageWidth - txt_score.width;
txt_score.y = 10;
txt_score.visible = false;
txt_score.selectable = false;
addChild(txt_score);
//----------------------------------------------------------------------------------------------------
function startQuiz(e:MouseEvent):void
{
// here we will get only 5 questions
// I used a method from http://stackoverflow.com/questions/11980657/as3-random-array-randomize-array-actionscript-3 to shuffle the array
// and then I remove the last 2 elements from the array
enabled_questions = enabled_questions.sort(function(i:*,j:*){return(Math.random()<.5)?-1:1;}).slice(0,enabled_questions.length-2);
for(var i:int = 0; i < enabled_questions.length; i++){
var q_i:int = enabled_questions[i];
var q:Object = questions_list[q_i];
max_score += q.score;
// create our questions instance and hide it
// every question is an instance of a movieclip in our library
// we can alse use only one movieclip and then we can use its timeline to go from a question to another
var question = new (q.movie_clip);
question.index = q_i;
question.visible = false;
questions_container.addChild(question);
}
// hide the start button
e.target.visible = false;
// show other elements
questions_container.visible = checks_container.visible = btn_next.visible = txt_score.visible = true
// load the first question
loadQuestion(current_question);
}
// check the answer and update score
function checkAnswer(e:MouseEvent):void
{
var question:Object = questions_list[enabled_questions[current_question]];
if(question.good_answer == checks_group.selectedData){
// update the score
setScore(question.score);
}
if(current_question < enabled_questions.length - 1){
current_question ++;
loadQuestion(current_question);
} else {
e.target.x = e.target.y = 0;
e.target.enabled = false;
e.target.width = stage.stageWidth;
e.target.height = stage.stageHeight;
e.target.label = 'You have finished the quiz, your score is : ' + score;
checks_container.visible = questions_container.visible = txt_score.visible = false;
}
}
// load question (show it) and update our check box
function loadQuestion(index:int):void
{
var question:Object = questions_list[enabled_questions[index]];
for(var i:int = 0; i < checks_container.numChildren; i++){
if(checks_container.getChildAt(i) is RadioButton){
var btn:RadioButton = RadioButton(checks_container.getChildAt(i));
switch (btn.name){
case 'btn_check0' : btn.value = btn.label = question.first_answer; break;
case 'btn_check1' : btn.value = btn.label = question.second_answer; break;
case 'btn_check2' : btn.value = btn.label = question.third_answer; break;
case 'btn_check3' : btn.selected = true; break;
}
}
}
for( i=0; i < questions_container.numChildren; i++){
if(questions_container.getChildAt(i) is MovieClip){
var mc:MovieClip = MovieClip(questions_container.getChildAt(i));
mc.visible = mc.index == question.index;
}
}
// setScore is used here just to update the question number in the score text field
setScore();
}
// show the score and current question
function setScore(new_score:int = 0){
score += new_score;
txt_score.text = 'Score : ' + score.toString() + ' / ' + max_score.toString() + ', Question : ' + (current_question+1) + ' / ' + enabled_questions.length;
}
// icons used in this example by Jozef Krajčovič : https://www.iconfinder.com/Jozef89
This code gives you something like this :
You can also see it working here.
Of course this is just a simple example, you can improve and adapt it to your needs.
Hope that can help.
Sounds like you just need a single submit button that goes to the next frame. That way you don't have to worry about the order.
Some sample code to give you an idea how it might work
var index = 0;
var currentQuestion:int = final_array[index];
var answers:Object = {
8158: '12',
8159: '13'
//...etc.
};
submitBtn.addEventListener(MouseEvent.CLICK, onSubmitClicked);
function onSubmitClicked(e:MouseEvent):void {
var answer:String = getAnswer(); //get the user's answer
if (answer === answers[currentQuestion]) {
awardScore(currentQuestion);
++index;
currentQuestion = final_array[index];
gotoAndStop(final_array[index]);
}
}
The idea is to have all that logic in a single click handler, once clicked it will grab the users answer and check if it is correct, if it is then it goes on to the next question.