Change value in $rootScope - javascript

I have a table with a background like this: http://ast-ss.se/terrain/
You can navigate through the boxes by just clicking on them. I have also implemented the feature that random monsters, black dots, is generated at the map. You can navigate to the box and challenge the monster.
When I click on a box with a monster in it, I get the monster's specifications, lever, strength etc etc.
Here is the code snippet from my directive:
if(angular.element(this).hasClass('monster'))
{
var monster_info = angular.element(this).find("img").attr("title");
$http.get("lib/terrain.php", {params: { monster_data:monster_info}}).success(function(data) {
console.log(data);
$rootScope.$broadcast('mapInfo', data);
});
}
As you can see, I'm using $rootScope.$broadcast for this. Here is what I'm doing in my controller:
$scope.$on('mapInfo', function(event, mapInfo) {
$scope.mapInfo = mapInfo;
console.log($scope.mapInfo);
});
And here is my HTML:
<div id="leftcontent_top">
<ul>
<li>Vildmarken</li>
<li> | </li>
<li>Marknaden</li>
<li> | </li>
<li>Värdshuset</li>
</ul>
</div>
<div ng-bind-html="safeHtml(mapInfo)"></div>
<div ng-if="challengeMonster"><input type="submit" ng-click="doChallenge()" value="Utmana"></div>
This works fine. The information about the monster is printed out at the page. However, when you are in a box without a monster, I want to display information about the box you are in. Everytime you navigate to a new box, I want to print out information about that box. I have tried like this:
Directive:
angular.element('.click').click(function() {
if(angular.element(this).hasClass('monster'))
{
var monster_info = angular.element(this).find("img").attr("title");
$http.get("lib/terrain.php", {params: { monster_data:monster_info}}).success(function(data) {
console.log(data);
$rootScope.$broadcast('mapInfo', data);
});
}
else
{
test = angular.element(this).attr('id');
$rootScope.$broadcast('mapInfo', test);
angular.element('.click.dotted').empty();
angular.element('.click.dotted').removeClass('dotted');
if(!angular.element(this).hasClass('dotted'))
{
$rootScope.$broadcast('mapInfo', test);
angular.element(this).addClass('dotted');
angular.element(this).html($('<img src="images/dot.png">'));
}
}
});
As you can see, I have an else-statement with $broadcast, but the value of test is not printed out at the page. But if I click on a box with a monster in it, the information is printed out, but if I click in a empty box, nothing is printed out. As you can see in the controller, I run console.log($scope.mapInfo) and I can see that $scope.mapInfo contains the correct value.
Anyone?

Related

Value not changed back when canceled

This is in angular. There is a p-table that shows some data, like below:
When I clicked on the pencil icon to edit the table row, this pops up. I'll call this the edit dialog:
When I make any kind of edit in the text input box, the table row on p-table also change to the new value; example if I change the Download URL to "sss", the p-table also shows "sss" even though I haven't clicked the "Update" button yet. However, if I decide to cancel the change by clicking on the Cancel button, the new value ("sss") stays and the old value does not revert back. Any help on reverting it back is appreciated.
Here is how my code is currently set up: when I open the page the first time, it retrieves the data in the table from a database and display in the p-table. When I click on the pencil icon, it uses DynamicDialog to open the edit dialog that was created by another component.
Here's the typescript code to that it uses to open the edit dialog, which is called ModelDialogComponent:
this.ref = this.dialogService.open(ModelDialogComponent, {
data: {
record,
},
header: title,
width: '500px',
contentStyle: { 'max-height': '500px' },
baseZIndex: 10000,
dismissableMask: true,
})
ModelDialogComponent has five input text and two buttons. Each of the input text is create in this similar fashion. This is one of the html code for it:
<!--Applicationn Name-->
<div class="p-field p-grid" style="padding: 10px">
<label class="p-col-fixed" style="width: 150px">App Name </label>
<div class="p-col">
<input type="text" pInputText readonly [(ngModel)]="updateData.app" />
</div>
</div>
The Cancel button is tied to a function: (click) ="cancelUpdate()"
cancelUpdate() is this:
cancelUpdate(){
this.config.data.record = this.clonedVersion;
this.config.data.record = {...this.config.data.record};
this.updateData = this.clonedVersion;
this.updateData = {...this.updateData};
this.ref.close(this.clonedVersion);
}
Here is ModelDialogComponent init:
ngOnInit() {
this.updateData = this.config.data.record;
this.clonedVersion = {...this.updateData};
}
Canceling does not revert the value back to its original value, and how do I do that?
If you need more info, please let me know.
I figured out a way to get it to revert back. use onClose, and then get the original data from the database. This works good for now because the database is small. As it grows, I think I will need to figure out why cloning the table row and setting it back does not work. Here's my code for the solution I made:
this.ref.onClose.subscribe(() => {
this.messageService.add({
severity:'info',
summary: 'Canceled Editing',
detail:'User canceled edits',
sticky: false,
});
this.ToolVersionService.getAllVersion().subscribe((data) => {
this.rowData = data;
this.loading = false;
this.EditDetails = false;
},
(err) => {
console.error(err)
});
});

How can I get rid of all duplicate watches in AngularJS?

I have created a simple TODO app with AngularJS.
So I have here a list of TODOs. I can delete , set as completed , and add new ones.
I can also edit the title via double clicking the bold text. And now - a text input will appear instead:
Basically , each row ( under the ng-repeat) has an invisible input which I play with its visibilkity :
<li ng-repeat="todo in vm.todos....." ...>
<div ng-hide="vm.isTheEdited(todo)"> //this is "read" mode
....show checkbox + Label + Delete button
</div>
<input ... show="vm.isTheEdited(todo)".... /> // this is the "edit" mode
</li>
All OK
But I saw this code which counts watchers in an App .
So I enhanced it to show unique items and in a string way.
(All I did was adding) :
Array.prototype.unique = function(a){
return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 })
console.log(getWatchers().unique().length);
console.log(getWatchers().unique().map(function (a){return a.exp;}));
)*
This is not important.
The important thing is that it has many duplicates watchers !!!
Look at the results :
Question
why do I have so many duplicates entries and how can I reduce the number of the watchers? (and eliminate dups)
All I did was to use ng-show and hide via some value of function.
In fact I don't think there isn't any duplicate: both ngShow an ngHide create a watcher and you can't do anything to avoid that using native directives: you should expect at least two watcher for each row in this case.
The only way to remove watchers (all of them) is to create a custom directive that:
hides the label and show the input on double click
shows the label and hide the input when pressing enter
Example:
module.directive('myClick', function() {
return {
link: function(scope, element) {
var span = element.find('span'),
input = element.find('input');
input.hide();
span.on('dblclick', function() {
if (span.is(':visible')) {
span.hide();
input.show();
input.val(span.text());
}
});
input.on('keypress', function(e) {
if (e.which === 13) {
input.hide();
span.show();
span.text(input.val());
}
});
}
}
});
Html:
...
<div ng-repeat="todo in vm.todos" my-click>
<span>{{todo}}</span><input>
</div>
...

adding and removing a class upon slidetoggle

I have created a 3 x 2 grid of squareish buttons that are monotone in colour. I have a slidetoggle div that pops down inbetween both rows of 3 and as it does so it pushes the content down of the rest of hte page, this is all working perfectly so far.
But i have made a class (.active) thats css is the same as the :hover state so that when i hover over a button the coloured version replaces the monotone version, however i have tried to add some js to make the colour (.active) stay on once i have clicked on a certain button so that you can see which button (product) the slidedown div relates to and the rest are still in monotone around it...
The .active code below works perfectly to turn the bottons colour on and off when you click that one button, but i have set it up so that if one button's div is open and you click on a different one, the open one closes and then the new one opens. This feature however throws off the balance of the code i have for the .active state here. When you have say button 1 open and you click button 1 to close, this works fine, the color goes on and then off, but if yo uhave button 1 open and click on button 2, button 1's div closes and opens button 2's div but then botton 1 stays in colour as button 2 turns to colour. the order is thrown off...
I need to add some js to say, that only one button can be in color (.active) at a time, or that if one is .active it must be turned off before the new one is turned on... Please help :)
$(document).ready(function(){
$("a.active").removeClass('active'); //<<this .active code &
$("#product1").click(function(){
if($(this).parent('a').hasClass('active')){ //<<<this .active code
$(this).parent('a').removeClass('active'); //<<
}else{ //<<
$(this).parent('a').addClass('active'); //<<
} //<<
$("#product2box").slideUp('slow', function() {
$("#product3box").slideUp('slow', function() {
$("#product4box").slideUp('slow', function() {
$("#product5box").slideUp('slow', function() {
$("#product6box").slideUp('slow', function() {
$("#product1box").stop().slideToggle(1000);
//do i need
//something here??
});
});
});
});
});
});
And here is the HTML
<div id="row1">
<a href="#!" class="active"><span id="product1">
<div id="productblueheader">
<div id="productlogosblue1"></div>
</div>
<div id="productstitle">Stops all spam and unwanted email.</div>
<div id="producttext">With over 8 million users ******* is the leading in anit-spam software on the market today! Sort all your spam issues in one place now!</div>
</span></a>
<a href="#!" class="active"><span id="product2">
<div id="productblueheader">
<div id="productlogosblue2"></div>
</div>
<div id="productstitle">The easiest email encryption ever.</div>
<div id="producttext">In todays world, we won’t enter personal details in to untrusted websites, but we send personal information via regular (insecure) email all the time.</div>
</span></a>
<a href="#!" class="active"><span id="product3">
<div id="productblueheader">
<div id="productlogosblue3"></div>
</div>
<div id="productstitle">The easiest email encryption ever.</div>
<div id="producttext">****** is a revelation in security and ease of use. Get the best protection against viruses, spyware, scam websites and other threats.</div>
</span></a>
</div>
(then the same for row2 products 4-6)
you use .each() method of jquery and find .active class to remove it,
and then add .active class.
$(this).parent('a').each(function(){
$(this).removeClass('active');
});
$(this).parent('a').addClass('active');
This ought to work, but I couldn't test it without the relevant HTML:
$(document).ready(function () {
$("#product1").click(function () {
$("a.active").removeClass('active');
$(this).parent('a').toggleClass('active'));
$("#product2box").slideUp('slow', function () {
$("#product3box").slideUp('slow', function () {
$("#product4box").slideUp('slow', function () {
$("#product5box").slideUp('slow', function () {
$("#product6box").slideUp('slow', function () {
$("#product1box").stop().slideToggle(1000);
});
});
});
});
});
});
});
Also, there would probably be a better way to write all those sliding up functions. Do they really need to go on by one by the way?
$(document).ready(function() {
$(".producthandler").click(function() {
var ctx = $(this);
var productboxId = ctx.children().eq(0).attr("id");
ctx.toggleClass('active');
$("#" + productboxId + "box").stop().slideToggle(1000);
$(".producthandler").each(function() {
var ctx = $(this);
var producthandlerId = ctx.children().eq(0).attr('id');
if (productboxId !== producthandlerId) {
ctx.removeClass('active');
$("#" + producthandlerId + "box").slideUp(1000);
}
});
});
});

Simple ToDo App using Agility.js with Persistence

I created a database called agilityjs that has a table called todolist. I created a file in /api/todolist.php which will act as a web service. I want to make it so when the user clicks "New Item," it will add a new item to my database by calling the PHP file (todolist.php). My next goal is to edit the item when they click to edit and delete when they click to delete.
Can anyone help me in the right direction? I have seen the persistence documentation at http://agilityjs.com/docs/docs.html#persist but I'm not sure how to apply it.
The following code is simply taken from http://agilityjs.com/ (at the bottom, you can see it and it's live demo).
Here is another good resource for learning https://gist.github.com/3166678, but I can't seem to apply it either.
//
// Item prototype
//
var item = $$({}, '<li><span data-bind="content"/> <button>x</button></li>', '& span { cursor:pointer; }', {
'click span': function(){
var input = prompt('Edit to-do item:', this.model.get('content'));
if (!input) return;
this.model.set({content:input});
},
'click button': function(){
this.destroy();
}
});
//
// List of items
//
var list = $$({}, '<div> <button id="new">New item</button> <ul></ul> </div>', {
'click #new': function(){
var newItem = $$(item, {content:'Click to edit'});
this.append(newItem, 'ul'); // add to container, appending at <ul>
}
});
$$.document.append(list);
Thank you.

Creating Dynamic Javascript AJAX

Alright, I'm currently working to create on an account mainpage a applet to show each "kid" the user has registered to the site. My idea is simple :
Kid 1 / Kid 2 / Kid 3
As buttons (with style and such) when he goes on this page. When he clicks on one of those buttons/names, I use javascript to show the description of the infos of the kid, etc. When I click on another name, the current content closes and shows the new appropriate content.
The content is dynamically created, so the id's of the divs containing the info are named after the number of kids. Example : content_Info_Kid1, content_Info_Kid2, ... It doesnt matter how many kids there are, they will be named content_Info_Kid32 if need be.
Now, I'm not too comfy with AJAX and javascript in general. In fact, I am not at all.
My first idea was to do this in a separate javascript file.
$(document).ready(function() {
$("#content_info_kid1").hide();
$("#content_info_kid2").hide();
$("#content_info_kid3").hide();
$("#KID_1").click(function () {
if ($("#content_info_kid1").is(":hidden")){
$("#content_info_kid2").hide();
$("#content_info_kid3").hide();
$("#content_info_kid1").show("slow");
$(this).css("font-weight","bold");
$("#KID_2").css("font-weight","normal");
$("#KID_3").css("font-weight","normal");
}
});
$("#KID_2").click(function () {
if ($("#content_info_kid2").is(":hidden")){
$("#content_info_kid1").hide();
$("#content_info_kid3").hide();
$("#content_info_kid2").show("slow");
$(this).css("font-weight","bold");
$("#KID_1").css("font-weight","normal");
$("#KID_3").css("font-weight","normal");
}
});
$("#KID_3").click(function () {
if ($("#content_info_kid3").is(":hidden")){
$("#content_info_kid2").hide();
$("#content_info_kid1").hide();
$("#content_info_kid3").show("slow");
$(this).css("font-weight","bold");
$("#KID_1").css("font-weight","normal");
$("#KID_2").css("font-weight","normal");
}
});
});
Obviously, this is not dynamic. And I don't want to create 32 alternatives, of course. Can somebody point me the right direction to create a dynamic way to show my content based on the number of kids ?
EDIT (see bottom for updated on loading just one kid data at a time)
An example on how you could achieve that:
<style type='text/css' media='screen'>
button { margin-left:20px; display:inline; }
</style>
<script type='text/javascript' src='jquery-1.7.1.min.js'></script>
<script type='text/javascript'>
function loadKidData(kidID) {
switch (kidID) {
case 1 : $('#kName').text(' John Doe');
$('#kNickname').text(' Speedy');
$('#kHobbies').text(' Booling');
break;
case 2 : $('#kName').text(' Mathews Doe');
$('#kNickname').text(' Slowy');
$('#kHobbies').text(' Basketball, baseball');
break;
case 3 : $('#kName').text(' Jackson Doe');
$('#kNickname').text(' J-DOE');
$('#kHobbies').text(' Archery');
break;
case n : $('#kName').text(' Enne Doe');
$('#kNickname').text(' The-Nanny');
$('#kHobbies').text(' Anything goes');
break;
default : $('#kName').text('');
$('#kNickname').text('');
$('#kHobbies').text('');
}
}
jQuery( function () {
$('.nav').click( function () {
loadKidData($(this).html().replace('KID ','')*1.0); // *1.0 same as parseInt(...,10).
})
});
</script>
</head>
<body>
<button class='nav' >KID 1</button><button class='nav' >KID 2</button><button class='nav' >KID 3</button>
<div id='KID_INFO' style='margin:20px auto; overflow:auto; ' >
<p>Name:<span id='kName'></span></p>
<p>Nickname:<span id='kNickname'></span> </p>
<p>Hobbies:<span id='kHobbies'></span> </p>
</div>
</body>
Sample at: http://zequinha-bsb.int-domains.com/kidsinfo.html
Now, as far as dynamically displaying the data, it will have to do with your resources: database? If so, you could read the data and pass it over:
$.get('url-of-the-database-reading-script',function (data) {
// assumed all data comes back formatted:
$('#KIDS_INFO').html(data);
});
I can/could help you further, more details would help. Are you using classic asp (.asp); php; etc?
EDIT:
Instead of this:
jQuery( function () {
$('.nav').click( function () {
loadKidData($(this).html().replace('KID ','')*1.0); // *1.0 same as parseInt(...,10)
})
});
Do this:
jQuery( function () {
$('.nav').click( function () {
$.get('your-data-fetching-url?kidID='+$(this).html().replace('KID ','')*1.0, function (data) {
//assumed the data comes back formatted:
$('#KIDS_DATA').html(data);
})
})
});
Note that I put a question mark at the end of the url; followed by the querystring kidID=
Give each "Kid" button the same class and use that for the click handler. From there, you can associate the "content_info_kid" with the "kid" button either by
1)Using the index of the element. The button for kid2 should be index 1 relative to its parent and the content_info for kid2 should also be index 1 relative to its parent.
or
2)Extract the number from the ID of the button.
Both approaches are documented below.
$('.kid_button').click(function(){
// get number from index (this starts at '0')
// if your kid #'s start at 1, you should add 1 to this
var id = $(this).index();
// OR...get number from id where id format is kid_{#}
var id = $(this).attr('id').split('_').pop();
// now we have the number to append to everything else
// we should also associate all "content_info" with a class
// which we will call "kid_content"
if($("#content_info_kid"+id).is(":hidden")){
// hide all of the 'kid_contents'
$(".kid_content").hide();
// show the one we want
$("#content_info_kid"+id).show("slow");
// normalize all buttons
$(".kid_button").css("font-weight","normal");
// bold this one
$(this).css("font-weight","bold");
}
});

Categories

Resources