6
\$\begingroup\$

I have this HTML down below that creates a list with two columns, the left one containing profile information, and the right one containing checkboxes of the user feedback in a horizontal list.

The list behaves so that when the element of the questionAnswer array is true, there is a font-awesome checked square, and when it is not true, there is just a bold square.

The checked boxes need to change color depending on a property of the object which, the way I chose to do it here, contains the name of the corresponding css class.

Then in ng-class, I stipulated that the color should be black, providing that the value of the ng-repeat at that point is false.

Is there a better way to do this? Should I write a directive instead?

Here is the current behavior visualized. Note the color changes in relation to the choice in the "You" field:

enter image description here

app.controller('ComparisonCtrl', function ($scope, $rootScope, $routeParams) {
    console.log("Inside ComparisonCtrl");


    $scope.currentUser = {
        You: {
            questionAnswer: [false, false, true, false, false, false],
            questionImportance: "Unimportant",
        }
    };

    $scope.profileCompare = {

        Pizza: {
            name: "Pizza",
            questionAnswer: [false, false, false, false, false, true],
            questionImportance: "Important",
            difference: undefined,
            office: "Cheese",
            index: undefined
        },
        GreenieBigNameGuy: {
            name: "Greenie Centipede",
            questionAnswer: [false, false, false, false, true, false],
            questionImportance: "Very Important",
            difference: undefined,
            office: "Green Beans",
            index: undefined
        },
        Red: {
            name: "Seeing Red",
            questionAnswer: [false, false, false, true, false, false],
            questionImportance: "Not Important",
            difference: undefined,
            office: "milk",
            index: undefined
        },
        Yellow: {
            name: "Christmas Tree",
            questionAnswer: [false, false, true, false, false, false],
            questionImportance: "Not Important",
            difference: undefined,
            office: "Elf",
            index: undefined
        },
        Yellow2: {
            name: "Buffalo Bill",
            questionAnswer: [false, true, false, false, false, false],
            questionImportance: "Not Important",
            difference: undefined,
            office: "grass",
            index: undefined
        }
    }

    $scope.setDifference = function(){
        var choice, differenceBetween, choice2
        
        for (key in $scope.profileCompare){
            if ($scope.profileCompare.hasOwnProperty(key)){
                for (var i = 0; i < $scope.currentUser.You.questionAnswer.length; i++){
                    if ($scope.currentUser.You.questionAnswer[i] == true){
                        choice = i;
                        console.log(choice);
                    }
                }
                for (var i = 0 ; i < $scope.profileCompare[key].questionAnswer.length; i++){
                    if ($scope.profileCompare[key].questionAnswer[i] == true){
                        choice2 = i;
                        differenceBetween = 0;
                    }
                }
                if (choice2 == choice) {
                    $scope.profileCompare[key].difference = "_0pcnt";
                    console.log("Difference for " + key
                     + " is " + $scope.profileCompare[key].difference);
                } else if (choice2 < choice) {
                    for (var i = 0; i < 6; i++){
                        choice2++
                        differenceBetween++
                        if(choice2==choice){
                            $scope.setDiffProperty(differenceBetween) 
                            break 
                        }
                    }
                } else if (choice < choice2) {
                    for (var i = 0; i < 6; i++){
                        choice++
                        differenceBetween++
                        if(choice2==choice){
                            $scope.setDiffProperty(differenceBetween)
                            break 
                        }
                    }
                }
            }
        }
    };


    $scope.setDiffProperty = function(differenceBetween){
        if (differenceBetween == 1){
            $scope.profileCompare[key].difference = "_20pcnt";
            console.log("Difference for " + key
            + " is " + $scope.profileCompare[key].difference);
        } else if (differenceBetween == 2){
            $scope.profileCompare[key].difference = "_40pcnt";
            console.log("Difference for " + key
            + " is " + $scope.profileCompare[key].difference);
        } else if (differenceBetween == 3){
            $scope.profileCompare[key].difference = "_60pcnt";
            console.log("Difference for " + key
            + " is " + $scope.profileCompare[key].difference);
        } else if (differenceBetween == 4){
            $scope.profileCompare[key].difference = "_80pcnt";
            console.log("Difference for " + key
            + " is " + $scope.profileCompare[key].difference);
        } else if (differenceBetween == 5){
            $scope.profileCompare[key].difference = "_100pcnt";
            console.log("Difference for " + key
            + " is " + $scope.profileCompare[key].difference);
        }
    }

};
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
	display: block;
}



ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
table {
	border-collapse: collapse;
	border-spacing: 0;
}

.nameAndImportance {
border:1px solid silver;
float:left;
margin:2px;
min-height:100px;
padding:2px;
width:50px;
display: inline-block;
};

.testItem {
border:1px solid silver;
float:left;
margin:2px;
min-height:100px;
padding:2px;
width:50px;
display: inline-block;
};

.skinnyVerticle {
	margin:2px;
	padding:2px;
	width:50px;
	min-height: 100px;
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
  border:1px solid silver;
}

.opinion {
border:1px solid silver;
float:left;
margin:5px;
min-height:100px;
padding:5px;
width:300px;
display: inline block;
};



/*------
*
*
*  styles.css - VoteWise
*  Version 1.0
*
*  Matias Salas
*  3-16-2015
*
*-------*/

body {
	line-height: 1;
	background-color: #c4e2fa;
	text-align: center;
	font-family: 'Gentium Basic', serif;
}



li {
	text-decoration: none;
}

a {
	text-decoration: none;
	color: #000;
}

a:hover {
	cursor: pointer;
}


/*
.backgroundImage {
	position: absolute;
    z-index: -1;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    opacity: .4;
    width: 100%;
    height: 100%;
}
*/
/*.main:after {
	background-size: 110%;
	opacity: 0.05;
	position: absolute;
	top: 2rem;
	left: 0;
	z-index: 1;
	width: 100%;
	height: 150%;
}*/

footer {
	height: 5.625rem;
}

.log-in{
	width: 150px;
	height: 35px;
	background-color:#fff;
	margin: .625rem auto 0;
	border: 5px solid #000;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	font-size: 1.2rem;
	text-transform: uppercase;
	letter-spacing: 2px;
}

.log-in-info{
	width: 120px;
	height: 30px;
	background-color:#fff;
	margin: .625rem auto 0;
	border: 5px solid #000;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	font-size: 1.2rem;
	letter-spacing: 2px;
}

.register{
	width: 200px;
	height: 30px;
	background-color:#fff;
	margin: .625rem auto 0;
	border: 5px solid #000;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	font-size: 1.2rem;
	letter-spacing: 2px;
}

.register-button {
	width: 150px;
	height: 35px;
	background-color:#fff;
	margin: .625rem auto 0;
	border: 5px solid #000;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	font-size: 1.2rem;
	text-transform: uppercase;
	letter-spacing: 2px;
}

.clearFix{
	height: 1px;
	clear: both;
}

.left {
	float: left;
}

.right {
	float: right;
}

.logo-home{
	background-image: url("../img/VotewiseLogo.png");
	background-size: 22.5rem 7.7rem;
	width: 22.5rem;
	height:7.7rem;
	margin: 0 auto;
}

.verticle-text {
	-webkit-transform: rotate(270deg);
	transform: rotate(270deg);
	

	-webkit-transform-origin: left top 0;
	transform-origin: left top 0;
	bottom: 8.125rem;
	
	position: absolute;
	font-size: 2.5rem;
	text-transform: uppercase;
	font-weight: 700;
}
.verticle-text a {
	text-decoration: none;
	color: #000;
}

.verticle-text a:hover {
	cursor: pointer;
	color: #ff4500;
}

.v-right {
	-webkit-transform: rotate(90deg);
	transform: rotate(90deg);
	

	-webkit-transform-origin: left top 0;
	transform-origin: left top 0;
	top: 3rem;
	left:21.8rem;
	width: 80%;
	
	position: absolute;
	font-size: 1.4rem;
	text-transform: uppercase;
	font-weight: 700;
	background-color: #dedede;
	border-radius: 20px;
	border:1px solid black;
	padding: .1rem 0;
}

.v-left {
	-webkit-transform: rotate(90deg);
	transform: rotate(90deg);
	

	-webkit-transform-origin: left top 0;
	transform-origin: left top 0;
	top: 3rem;
	left:1.6rem;
	width: 70%;
	
	position: absolute;
	font-size: 1.4rem;
	text-transform: uppercase;
	font-weight: 700;
	background-color: #dedede;
	border-radius: 20px;
	border:1px solid black;
	padding: .1rem 0;
}

.portal{
	background-size: 8.4375rem 12.7rem;
	width: 8.4375rem;
	height:12.7rem;
	-webkit-transition: all .2s ease-in-out;
	-moz-transition: all .2s ease-in-out;
	transition: all .2s ease-in-out;
}

.portal:hover {
	-webkit-transform: scale(1.05);
	-moz-transform: scale(1.05);
	transform: scale(1.05);
}

 .row a {
	width: 8.4375rem;
	height:13.4375rem;
}

.voterbox {
	background-image: url("../img/VOTER.svg");
	background-repeat: no-repeat;
	float: left;
}

.politicianbox {
	background-image: url("../img/POLITICIAN.svg");
	background-repeat: no-repeat;
	float: right;
}

.overflow {
	max-height:350px;
	overflow:scroll;
}

.flex-container-interests {
  padding: 0;
  margin: 0;
  list-style: none;
  
  display: -moz-flex;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  display: -webkit-flex;
  
  flex-flow: row wrap;
  -webkit-box-flex-flow: row wrap;
  -webkit-flex-flow: row wrap;
  -ms-flex-flow: row wrap;
  -moz-flex-flow: row wrap;


  justify-content: space-around;
  -webkit-justify-content: space-around;
}

.politicianAnswers {
	width:360px;
	height:360px;
	overflow: scroll;
}

/*.main{
	width:40rem;
	margin: 0 auto;
	position: relative;
	font-weight: 700;
}*/



@media screen and (max-width: 767px){

	.main{
		width:90%;
		margin: 0 auto;
		position: relative;
	}

	.comparisons {
		margin-bottom: 1rem;
		line-height: 2em;
		/*word-spacing: px;*/
		/*letter-spacing: .05rem;*/
		width:100%;
	}

	.comparisonButton {
	  display: block;
	  width: 200px;
	  height: 43px;
	  background: navy;
	  padding: 7px;
	  text-align: center;
	  border-radius: 20px;
	  color: white;
	  font-weight: bold;
	}

	.comparisons p {
		text-transform: none;
		text-align: justify;
		line-height: 2rem;
		width: 85%;
		margin: 0 auto;
		font-size: 1.75rem;
	}

	.result {
	    float: right;
	    width: 100%;
	    display: inline-block
	    ;
	}
	.center {
		text-align: center;
	}
	.right {
		/*text-align: right;*/
		position:relative;
		float:left;
	}
	.left {
		text-align: left;
	}

	.result ul li{
	    display: inline-block;
	    list-style-type: none;
	    padding: 1em;
	    width: .4em;
	    text-align: right;
	    font-size:1em;
	    position:relative;
	    float:right ;
	}

	.brd {
		border: 1px solid black;
	}

	.result tr td table{
		display: inline-block;
		padding: 4em;
		width: 1em;
		display: ;
	}
	.result-b {
	    float: right;
	    width: 100%;
	    display: inline-block;
	}

	.result-b ul li{
	    display: inline-block;
	    list-style-type: none;
	    padding: 1em;
	    width: .4em;
	    text-align: right;
	    font-size:1em;
	    position:relative;
	    float:right ;
	}

	.result-b tr td table{
		display: inline-block;
		padding: 4em;
		width: 1em;
		display: ;
	}


	.result1 {
	    float: left;
	    width: 34%;
	    position:relative;
	    left: 10px;

	}

	.result1 ul li{
	    display: inline-block;
	    list-style-type: none;
	    padding: 1em;
	    width: .4em;
	    text-align: right;
	    font-size:1em;
	    position:relative;
	    right:25px;
	}

	.flex-item-interests {

		padding: 0px;
		min-height: 125px;
		min-width: 125px;
		max-height: 125px;
		max-width: 125px;
		width: 100%;
		height: 100%;
		margin-top: 10px;
		margin-bottom: 40px;
		margin-right: 3px;
		margin-left: 2px;

		-webkit-flex: 1 1 7em;
		-moz-flex: 1 1 15em;
		flex: 1 1 15em;

		line-height: 20px;
		color: white;

	}

	.flex-item-interests img {
		-webkit-transition: all .2s ease-in-out;
		-moz-transition: all .2s ease-in-out;
		transition: all .2s ease-in-out;
		min-height: 125px;
		min-width: 125px;
		width: 100%;

	}

}

@media screen and (min-width: 768px) and (max-width: 992px){
	
	.comparisons {
		font-size: 1.4rem;
		margin-bottom: 1rem;
		line-height: 140%;
		/*word-spacing: px;*/
		/*letter-spacing: .05rem;*/
	}

	.comparisons p {
		text-transform: none;
		text-align: justify;
		line-height: 1.rem;
		width: 80%;
		margin: 0 auto;
	}

	.result1 {
	    float: left;
	    width: 30%;
	    position:relative;
	    left: 10px;
	    font-size:1.4em;

	}

	.result1 ul li{
	    display: inline-block;
	    list-style-type: none;
	    padding: 1em;
	    width: .4em;
	    text-align: right;
	    font-size:1em;
	    position:relative;
	    right:25px;
	}

	.result {
	    float: left;
	}

	.result ul li{
	    display: inline-block;
	    list-style-type: none;
	    padding: 1em;
	    width: .4em;
	    text-align: right;
	    font-size:1.6em;
	    position:relative;
	    right:25px;
	}

	.result tr td table{
		display: inline-block;
		padding: 4em;
		width: 1em;
		display: ;
	}

	.result tr td table{
		display: inline-block;
		padding: 4em;
		width: 1em;
		display: ;
	}

	.flex-item-interests {

	  padding: 0px;
	  min-height: 150px;
	  min-width: 150px;
	  max-height: 150px;
	  max-width: 150px;
	  width: 100%;
	  height: 100%;
	  margin-top: 10px;
	  margin-bottom: 30px;
	  -webkit-flex: 1 1 10em;
	  -moz-flex: 1 1 15em;
	  flex: 1 1 15em;

	  line-height: 10px;
	  color: white;
	}

	.flex-item-interests img {
	    -webkit-transition: all .2s ease-in-out;
		-moz-transition: all .2s ease-in-out;
		transition: all .2s ease-in-out;
		min-height: 150px;
		min-width: 150px;
		width: 70%;
	}
}

@media screen and (min-width: 993px){
	.flex-item-interests {

	  padding: 0px;
	  min-height: 200px;
	  min-width: 200px;
	  max-height: 200px;
	  max-width: 200px;
	  width: 100%;
	  height: 100%;
	  margin-top: 10px;
	  margin-bottom: 30px;
	  margin-right: 10px;
	  margin-left: 10px;
	  -webkit-flex: 1 1 12em;
	  -moz-flex: 1 1 15em;
	  flex: 1 1 15em;

	  line-height: 10px;
	  color: white;

	}

	.flex-item-interests img {
	    -webkit-transition: all .2s ease-in-out;
		-moz-transition: all .2s ease-in-out;
		transition: all .2s ease-in-out;
		min-height: 200px;
		min-width: 200px;
		width: 70%;

	}
}

.flex-item-interests p {

}

.flex-item-interests a {
  font-weight: bold;
  line-height: 15px;
  font-size: 1em;
  text-align: center;
  	-webkit-transition: all .2s ease-in-out;
	-moz-transition: all .2s ease-in-out;
	transition: all .2s ease-in-out;
/*  line-height: 100px;
*/}

.flex-item-interests a:hover {
	-webkit-transform: scale(1.05);
	-moz-transform: scale(1.05);
	transform: scale(1.05);
}


.interest-group {
	background-image: url("../img/INTEREST_GROUP.svg");
	background-repeat: no-repeat;
	float: left;
}

.press {
	background-image: url("../img/PRESS.svg");
	background-repeat: no-repeat;
	float: right;
}

nav {
  width: 100%;
  height: 100%;
  border-bottom: 10px solid #000080;
  margin-bottom: 1rem;
}

.nav-link {
	width:22.5rem;
	margin: 0 auto;
	height: 2.5rem;
	/*display: inline;*/
}


.nav-link li {
	opacity: 1;
	height: 2rem;
	width: 3.75rem;
	float: left;
}


.nav-link img {
	height: 2rem;
	width: 2rem;
	margin: 2px .5rem;
}


.nav-link a {
	height: 48px;
	cursor: pointer;
}

.nav-link li.hide {
	opacity: 0;
}

.overlay img{
	background-size: 110%;
	opacity: 0.05;
	position: absolute;
	top: 2rem;
	left: 0;
	z-index: 1;
	width: 100%;
	height: 150%;

}

.red { 
	color: red;
}

.green {
	color: forestgreen;
}

._100pcnt {
	color:#990000;
}

._80pcnt {
	color: #cc3300;
}

._60pcnt {
	color:#ff9933;
}

._40pcnt {
	color:#FCDC3B;
}

._20pcnt {
	color:#99cc00;
}

._0pcnt {
	color:#009900;
}

.orange {
	color:darkorange;
}

.black {
	color:black;
}

.blue {
	color: navy;
}

.comparison-true {

}

.comparison-false {

}

.comparison-list li
{
display: inline;
list-style-type: none;
padding-right: 20px;
}

.comparisonsOpinion {
	font-size: .8em;
	display: inline;
	text-align: right;
}

.comparisonProfile {
	display: inline;
	text-align: left;
}


.comparisons-background {
/*	-webkit-transform: rotate(90deg);
	transform: rotate(90deg);*/
	

/*	-webkit-transform-origin: center top 0;
	transform-origin: center top 0;*/
	margin: 0 auto;
	top: 3rem;
	left:1.6rem;
	width: 90%;
	text-align:center;
	float:center;
	vertical-align: baseline;

/*	position: absolute;

*/	font-size: 1rem;
	text-transform: uppercase;
	font-weight: 700;
	background-color: teal;
	border-radius: 20px;
	border: 1px solid black;
	padding: .1rem 0;
}

.comparisons-background a {
	text-align: center;
}

.talking-points {
	text-transform: uppercase;	
	z-index: 2;
}

.talking-points div:after {

}

.talking-points h2 {
	font-size: 2rem;
	margin-bottom: 2rem;
	letter-spacing: .3rem;
	opacity: 1;	
}
.talking-points h3 {
	font-size: 1.2rem;
	margin-bottom: 1.5rem;
	letter-spacing: .3rem; 
}

.talking-points li {
	list-style: disc;
	font-size: 1.5rem;
	text-align: left;
	margin-left: 3rem;
	margin-bottom: 0.8rem;
}

.talking-points p {
	text-transform: none;
	text-align: justify;
	line-height: 1.5rem;
	width: 70%;
	margin: 0 auto;
}

.talking-points span {
	font-size: .7rem;
}

p.privacy {
	float: left;
	margin: -1rem 0 0 1rem;
	text-transform: uppercase;
}

form {
	text-align: center;
	width: 75%;
	font-weight: 700;
	margin: 0 auto;
}

form h4 {
	text-transform: uppercase;
	margin: .5rem 0;
	font-size: 1rem;
}

form p {
	font-size: .7rem;


}

form p.right {
	text-align: right;
	width: 4rem;
	line-height: .7rem;
}

form div.left.poll input {
	margin: 0.5rem .7rem;
	float: left;

}

form div.left.poll {
	border-right: 1px solid black;
}

form div.right.poll input {
	margin: 0.5rem .7rem;
	float: right;
}

form p.left {
	text-align: left;
	width: 4rem;
	line-height: .7rem;
}

form .poll {
	height: 3rem;
	width: 49%;
	margin-bottom: .7rem;
}


form input[type="button"] {
	margin: 0 .2rem 1rem .2rem;
	background-color: white;
	border: 1px solid black;
}


form .next-question {
	font-size: 1rem;
	margin-top: 2rem;
	float: right;
}

form .fa-arrow-circle-right {
	margin-top: 2rem;
	float: right;
}

form .fa-arrow-circle-right:hover {
	cursor: pointer;
}

form input.comments {
	margin-left: 3.5rem;
}



.error-msg {
	font-size: 2rem;
	text-transform: uppercase;
	margin-top: 6.25rem;
}


/*--animations--*/


@-webkit-keyframes bounce {
  0%{
    right:-10px;
  }
  
  25%, 75% {
    right:-20px;
  }
  
  
  50% {
    right:-25px;
  }
  
  100% {
    right:-10px;
  }
}


@keyframes bounce {
  0%{
    right:-10px;
  }
  
  25%, 75% {
    right:-20px;
  }
  
  50% {
    right:-25px;
  }
  
  100% {
    right:-10px;
  }
}

.bounce {
	position:fixed;
  	bottom:0;
  	right:-10;
  	-webkit-animation: bounce .8s linear infinite;
  	animation: bounce .8s linear infinite;

}


/*---ng-cloak---*/
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
	display: none !important;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="overflow">
	<div class="row">
<button type="button" ng-click="setDifference()"> Button Test </button>
		<div class="col-xs-3">
			<div style="line-height:70%; height:100px; width:300px" class="right" ng-repeat="(key,profile) in profileCompare track by $index">
				<p style="font-size:1.5em; position:relative; top:10px; left:10px">{{profile.name}}:&nbsp
					<i ng-if="profile.questionImportance=='Very Important'" style="font-size:.7em>
						{{profile.questionImportance}}
					</i>
				</p>
				<p style="font-size:1em; position:relative; top:15px; left:10px">{{profile.office}}</p>
				<p style="font-size:1em; position:relative; top:15px; left:10px;">Comments</p>
			</div>
		</div>
		<div class="col-xs-9 center">
			<div class="" style="height: 100px"ng-repeat="(key,profile) in profileCompare track by $index">
				<ul style="position:relative; left:15px"> 
					<br style="font-size:1.3em">
			        <li ng-repeat="answer in profile.questionAnswer track by $index" style="top:10px; display:inline; font-size:1.57em;right: 10px; width:25px" class="">

			        	<i class="fa center {{profile.difference}}" ng-class="{'fa-check-square':answer, 'fa-square':!answer, 'black':!answer}">
			        		&nbsp&nbsp
			        		<i ng-if="$first" style="position:absolute; font-size:.45em; color:black; right: 2px; top:25px">
			        			Agree
			        			<i style="position:absolute; font-size:1em; color:black; bottom: 0px; left:72px">
			        			Ambivalent
			        			</i>
			        		</i>
			        		<i ng-if="$last" style="position:absolute; font-size:.45em; color:black; right: 11px; top:25px;">
			        			Disagree
			        		</i>
			        	</i>
			        </li>
	       		</ul>
			</div>	
		</div>
	</div>
</div>

\$\endgroup\$
  • \$\begingroup\$ it could work @realisation. it has to work before we will even review it. those are the rules of Code Review. doesn't work in FireFox or IE \$\endgroup\$ – Malachi Aug 13 '15 at 21:06
  • \$\begingroup\$ Works in my angular app :0. But could it be better? Oh, and I use font-awesome for the checkboxes. They are in ng-class part. What do you mean by saying "it has to work"? \$\endgroup\$ – realisation Aug 13 '15 at 21:08
  • \$\begingroup\$ Oh great! I just saw that second comment. This is what I did, mind you, but I also wondered if its perhaps a use case for a directive. No harm there, right? \$\endgroup\$ – realisation Aug 13 '15 at 21:10
  • \$\begingroup\$ you should read the Help section of Code Review that talks about what is On-Topic for Code Review \$\endgroup\$ – Malachi Aug 13 '15 at 21:12
  • \$\begingroup\$ Angular is supported in the stack snippet, so it should work, right? \$\endgroup\$ – Malachi Aug 13 '15 at 21:12
4
+100
\$\begingroup\$

Directives

In your $scope.profileCompare object, you have multiple objects like this inside:

Pizza: {
    name: "Pizza",
    questionAnswer: [false, false, false, false, false, true],
    questionImportance: "Important",
    difference: undefined,
    office: "Cheese",
    index: undefined
},

You have objects like in $scope.profileCompare that are all being displayed to the HTML using ng-repeat.

Hmm. Let's think about this. You are repeating very similar objects all dedicated to one purpose in your HTML... sounds like it's time for a directive!


Angular's directives allow for HTML to, like normal code comments should, explain why and not how.

It is much easier to read HTML code that has a directive in it than it is to guess about the how the rendered HTML tags would look on the user's screen. When someone is just reading your HTML code, that doesn't matter.


Let's go slowly through creating this directive. First, let's start blank:

app.directive("profilingCheckbox", function() {
    return {
    };
});

That is basically what the directive is going to look like. However, this doesn't do anything yet: we still need to add the HTML.


Creating a directive from existing HTML is quite easy in fact, especially if you were already using ng-repeat to show these elements before.

To get the HTML for our directive, we must first find the section that we are repeating and cut that all out.

I did a little searching through your HTML and found this:

<div class="" style="height: 100px"ng-repeat="(key,profile) in profileCompare track by $index">

This element's children is the child that is being repeated; the child that we are trying to grab and stick into it's own directive.

So now, the next step is really simple:

  1. Cut out the children of this element.

  2. Stick 'em into their own HTML file.

After you've done that, our directive now becomes:

app.directive("profilingCheckbox", function() {
    return {
        templateUrl: "profiling_checkbox.html"
    };
});

Now, the directive is going to show whatever HTML is inside the profiling_checkbox.html file, which is the file that you just created.


Next, we want to restrict this directive to elements-only. This means that this directive can only be an element: it's not supposed to be an attribute nor is it supposed to be a class.

This step is relatively simple:

app.directive("profilingCheckbox", function() {
    return {
        templateUrl: "profiling_checkbox.html",
        restrict: "E"
    };
});

Now, this directive can only be used in element-form.


There are still some problems with this directive. The biggest one? Scope.

Right now, there would be some major problems if you were to try and use this directive because, since there are going to be multiple elements with this directive, there would be repeats and what-not in the directives' content because they are all using the same scope.

To fix this, we can add a scope property to the object that our directive is returning. This property allows the directive to define attributes that it will read and then pass on to it's template in it's own scope. This makes sure there is no overlap and repeat when using multiple elements with this directive.

Adding the scope property would look like this:

app.directive("profilingCheckbox", function() {
    return {
        templateUrl: "profiling_checkbox.html",
        restrict: "E",
        scope: {

        }
    };
});

Right now, the scope property is empty. Before we populate it, we need to figure out, "What do we want to put here?" and "What does the template need?"

Well, it's quite simple to find out what the template needs: the original HTML code was in an ng-repeat so the template is obviously going to need whatever was in the ng-repeat.

After looking at your HTML again, it seems that the children of that element that was isolated above only use the profile from the ng-repeat. That being known, we can now change our directive to this:

app.directive("profilingCheckbox", function() {
    return {
        templateUrl: "profiling_checkbox.html",
        restrict: "E",
        scope: {
            profile: "="
        }
    };
});

This may be a little confusing. Basically, what this is saying is that the directive is going to read the attribute by the name "profile", and pass it on as a "parameter" to the template under the name "profile".

When using the directive, it would look like this:

<profiling-checkbox profile="profile"></profiling-checkbox>

If we just wanted the attribute to be "p", we could write:

profile: "=p"

Then, the using the directive would look like this:

<profiling-checkbox p="profile"></profiling-checkbox>

Controllers inside directives

Now that we have this handy-dandy new directive, we should probably move some of the code of our main controller into this directive's controller. That way, the information that the directive needs to know is with that directive and not spread out somewhere else in the code.


To add a controller to our directive, we simply need to add the controller property to the object that we are returning:

return {
    ...
    controller: function($scope) {

    }
}

Now, all the controller information would go in this function. It is just like a normal controller that you would write.

Note: Although I am not 100% certain, you may need to add transclude: true to the object that you are returning. This will allow the controller to access to the scope outside of the directive, rather than just in the directive.


All that's left to do with this controller is to move some of the information from your original controller into this controller.

For example, you might want to move $scope.currentUser and $scope.profileCompare

In order to properly deem what should and shouldn't be moved, remember this: a controller/directive should only accomplish one task. If you need to accomplish another task, you need another controller/directive.


CSS

You have this giant clump of element tags in your CSS file:

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {

You aren't even using half of these. I recommend that you all of the elements that you do not need; it's adding serious unreadable noise to your code.

\$\endgroup\$
2
\$\begingroup\$

There's a few points to point out about this:


The following snippet's parent block needs to be DRYed:

    if (differenceBetween == 1){
        $scope.profileCompare[key].difference = "_20pcnt";
        console.log("Difference for " + key
        + " is " + $scope.profileCompare[key].difference);
    } 

It's basically indentical code, except for differenceBetween and _*0pcnt.

A simple observation points out 1 = 20, 2 = 40, 3 = 60, 4 = 80, 5 = 100

So, just do:

    $scope.profileCompare[key].difference = ["_", differenceBetween * 20, "pcnt"].join('');
    console.log(["Difference for", key, "is", $scope.profileCompare[key].difference].join(' '));

The keys in $scope.profileCompare seem a little superfluous, you can just use a general array there, with array indexes instead.

Pizza: {
GreenieBigNameGuy: {

What happened to the indentation here?

.nameAndImportance {
border:1px solid silver;
float:left;
margin:2px;
min-height:100px;
padding:2px;
width:50px;
display: inline-block;
};

.testItem {
border:1px solid silver;
float:left;
margin:2px;
min-height:100px;
padding:2px;
width:50px;
display: inline-block;
};

The .currentUser object seems a bit superfluous also.

$scope.currentUser = {
    You: {
        questionAnswer: [false, false, true, false, false, false],
        questionImportance: "Unimportant",
    }
};

There should only be one currentUser, and with that having You in there is superfluous, by keeping it as an object just with the questionAnswer and questionImportance would be much simpler.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.