I have a div box002, On dragging and droping it to any of three class box with randomly selected numbers from a constant array named array2, the item should get deleted from array2.
for that i have created object of rvalue() function and tried to remove item in const filteredItems but didn't worked.
Where is the mistake,
How to achieve it?
var tempimages = [];
function rvalue() {
var items = [
{ label: '1:40', url: '1.png' },
{ label: '2:20', url: '2.png' },
{ label: '3:50', url: '3.png' },
{ label: '4:45', url: '4.png' },
{ label: '5:35', url: '5.png' },
{ label: '6:10', url: '6.png' },
{ label: '7:15', url: '7.png' },
{ label: '8:10', url: '8.png' },
{ label: '9:30', url: '9.png' },
{ label: '10:40', url:'10.png' },
{ label: '11:20', url:'11.png' },
{ label: '12:50', url:'12.png' },
{ label: '01:45', url:'13.png' },
{ label: '02:25', url:'14.png' },
{ label: '03:40', url:'15.png' },
{ label: '04:15', url:'16.png' },
{ label: '05:10', url:'17.png' },
{ label: '06:30', url:'18.png' },
{ label: '07:35', url:'20.png' }
]
ptags = document.querySelectorAll('[name="values"]');
const array2 = Object.assign([], items);
for (let index = 0; index < 3; index++)
{
randomIndex = Math.floor(Math.random() * items.length),
item = items[randomIndex];
ptags[index].textContent = item.label;
tempimages.push({data:item, index: randomIndex});
ptags[index].dataset.itemIndex = randomIndex;
}
}
function displayAllImages() {
if (tempimages.length === 0)
{
return;
}
item = tempimages.shift(),
image = document.getElementById('slide');
image.src = item.data.url;
image.dataset.itemIndex = item.index;
};
$(function() {
rvalue();
displayAllImages();
});
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
console.log(ev.srcElement);
var data = ev.dataTransfer.getData("Text");
var el = document.getElementById(data);
alert(data);
alert(el);
var x=document.getElementById("slide").dataset.itemIndex;
var y = ev.target.dataset.itemIndex;
alert("x=>" + x + " y=>" + y);
if(x==y)
{
//alert("go");
el.parentNode.removeChild;
ev.currentTarget.style.backgroundColor = 'initial';
var pParagraph = ev.currentTarget.firstElementChild;
ev.currentTarget.removeChild(pParagraph);
var ob1=new rvalue();
var delitem=ob1.item;
var filteredItems = array2.filter(item => item!== valueToRemove)
console.log(filteredItems);
console.log(delitem);
displayAllImages();
}
else{
alert("WRONG PLACE");
}
}
.box002 {
width: 30px;
height: 30px;
float: left;
border:2px solid #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)" id="10"><p name="values"></p></div>
<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)" id="11"><p name="values"></p></div>
<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)" id="12"><p name="values"></p></div>
</div>
<div class="box002" draggable="true" ondragstart="drag(event)" id="2">
<img src="" draggable="true" id="slide" style="width:120px; height:120px; border-radius: 50%;" border="rounded"/>
</div>
Because of this you can't change a constant, since they're... constant
The value of a constant cannot change through reassignment, and it can't be redeclared.
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.
To be able to alter any entry in your array, just make it a var or a let-variable.
Related
So, I'm trying to modify an already existing html file (uses embedded javascript) and change the way it outputs table data. The data that is being inputted into the table is being pulled from another program which stores this one value I want to change as a decimal value. Scouring through the code, I found the section that actually handles what data will be displayed to the table, and it as follows.
var bodyDefine =
[
//{ text: rankingText, width: "5%", align: "center", effect: deadYatsuEffect },
{ text: "{name}", width: "10%" },
{ text: "{Job}", width: "8%", align: "left" },
{ text: "{encdps}", width: "20%", align: "right" },
//{ text: "{damage%}", width: "5%", align: "right" },
//{ text: "{enchps}", width: "16%", align: "right" },
//{ text: "{healed%}", width: "5%", align: "right" },
//{ text: "{tohit}%", width: "16%", align: "right" },
//{ text: "{crithit%}", width: "14%", align: "right" },
];
Edit:
The current output is as follows(example):
Name Job DPS
|John Smith NIN 12653.25 |
|Adam Cook SAM 14577.32 |
But the intended output I want is without the decimal values under DPS.
Name Job DPS
|John Smith NIN 12653 |
|Adam Cook SAM 14577 |
This file was retrieved from https://github.com/hibiyasleep/OverlayPlugin/releases/tag/0.3.4.0 and is used with the program Advanced Combat Tracker with the FFXIV_ACT Plugin. The file below is located in the following directory OverlayPlugin-0.3.4.0-x64-full/resources/miniparse.html
The entire code:
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--STYLE SECTION REMOVED-->
<script>
//
// プラグイン側から以下のような ActXiv オブジェクトとしてデータが提供される
//
// var ActXiv = {
// "Encounter": {...},
// "Combatant": {
// "PlayerName1": {...},
// "PlayerName2": {...},
// ...
// }
// };
//
// データの更新は 1 秒毎。
//
// プラグインから onOverlayDataUpdate イベントが発行されるので、それを受信することもできる
// イベントハンドラの第一引数の detail プロパティ内に上記のオブジェクトが入る
//
//
// 表示設定 (2)
//
// エンカウント情報の定義
var encounterDefine = "{title} / Time: {duration} / DPS: {ENCDPS}";
// 上記のエンカウント情報を HTML として扱うなら true
var useHTMLEncounterDefine = false;
// ヘッダの定義
var headerDefine =
[
//{ text: "#", width: "5%", align: "center" },
{ text: "Name", width: "10%", align: "left" },
{ text: "Job", width: "8%", align: "left" },
{ text: "DPS", width: "20%", align: "right"},
//{ text: "HPS (%)", width: "18%", align: "center", span: 2 },
//{ text: "Acc.(%)", width: "16%", align: "right" },
//{ text: "Crt.(%)", width: "14%", align: "right" },
];
// 表示するデータの定義
var bodyDefine =
[
//{ text: rankingText, width: "5%", align: "center", effect: deadYatsuEffect },
{ text: "{name}", width: "10%" },
{ text: "{Job}", width: "8%", align: "left" },
{ text: "{encdps}", width: "20%", align: "right" },
//{ text: "{damage%}", width: "5%", align: "right" },
//{ text: "{enchps}", width: "16%", align: "right" },
//{ text: "{healed%}", width: "5%", align: "right" },
//{ text: "{tohit}%", width: "16%", align: "right" },
//{ text: "{crithit%}", width: "14%", align: "right" },
];
// 順位を表示する(text に関数を指定する例)
// 引数:
// combatant : キャラクターのデータ。combatant["..."]でデータを取得できる。
// index : キャラクターの並び順。一番上は 0 で、その後は 1 ずつ増える。
// 戻り値:
// 表示するテキスト。
// ACT のタグは展開されないので、展開したい場合は parseActFormat 関数を使用してください。
function rankingText(combatant, index) {
// 1 から始まる番号を返す
return (index + 1).toString();
}
// 死亡奴を赤くする(effect の例)
// 引数:
// cell : セルの DOM 要素
// combatant : キャラクターのデータ。combatant["..."]でデータを取得できる。
// index: キャラクターの並び順。一番上は 0 で、その後は 1 ずつ増える。
// 戻り値: なし
function deadYatsuEffect(cell, combatant, index) {
// デス数を整数値に変換
var deaths = parseInt(combatant["deaths"]);
// デス数が 0 よりも大きいなら
if (deaths > 0) {
// 赤くする
cell.style.color = "#FFA0A0";
cell.style.textShadow = "-1px 0 3px #802020, 0 1px 3px #802020, 1px 0 3px #802020, 0 -1px 3px #802020";
}
}
//
// 以下表示用スクリプト
//
// onOverlayStateUpdate イベントを購読
document.addEventListener("onOverlayStateUpdate", function (e) {
if (!e.detail.isLocked) {
displayResizeHandle();
} else {
hideResizeHandle();
}
});
function displayResizeHandle() {
document.documentElement.classList.add("resizeHandle");
}
function hideResizeHandle() {
document.documentElement.classList.remove("resizeHandle");
}
// onOverlayDataUpdate イベントを購読
document.addEventListener("onOverlayDataUpdate", function (e) {
update(e.detail);
});
// 表示要素の更新
function update(data) {
updateEncounter(data);
if (document.getElementById("combatantTableHeader") == null) {
updateCombatantListHeader();
}
updateCombatantList(data);
}
// エンカウント情報を更新する
function updateEncounter(data) {
// 要素取得
var encounterElem = document.getElementById('encounter');
// テキスト取得
var elementText;
if (typeof encounterDefine === 'function') {
elementText = encounterDefine(data.Encounter);
if (typeof elementText !== 'string') {
console.log("updateEncounter: 'encounterDefine' is declared as function but not returns a value as string.");
return;
}
} else if (typeof encounterDefine === 'string') {
elementText = parseActFormat(encounterDefine, data.Encounter);
} else {
console.log("updateEncounter: 'encounterDefine' should be string or function that returns string.");
return;
}
// テキスト設定
if (!useHTMLEncounterDefine) {
encounterElem.innerText = parseActFormat(elementText, data.Encounter);
} else {
encounterElem.innerHTML = parseActFormat(elementText, data.Encounter);
}
}
// ヘッダを更新する
function updateCombatantListHeader() {
var table = document.getElementById('combatantTable');
var tableHeader = document.createElement("thead");
tableHeader.id = "combatantTableHeader";
var headerRow = tableHeader.insertRow();
for (var i = 0; i < headerDefine.length; i++) {
var cell = document.createElement("th");
// テキスト設定
if (typeof headerDefine[i].text !== 'undefined') {
cell.innerText = headerDefine[i].text;
} else if (typeof headerDefine[i].html !== 'undefined') {
cell.innerHTML = headerDefine[i].html;
}
// 幅設定
cell.style.width = headerDefine[i].width;
cell.style.maxWidth = headerDefine[i].width;
// 横結合数設定
if (typeof headerDefine[i].span !== 'undefined') {
cell.colSpan = headerDefine[i].span;
}
// 行揃え設定
if (typeof headerDefine[i].align !== 'undefined') {
cell.style["textAlign"] = headerDefine[i].align;
}
headerRow.appendChild(cell);
}
table.tHead = tableHeader;
}
// プレイヤーリストを更新する
function updateCombatantList(data) {
// 要素取得&作成
var table = document.getElementById('combatantTable');
var oldTableBody = table.tBodies.namedItem('combatantTableBody');
var newTableBody = document.createElement("tbody");
newTableBody.id = "combatantTableBody";
// tbody の内容を作成
var combatantIndex = 0;
for (var combatantName in data.Combatant) {
var combatant = data.Combatant[combatantName];
var tableRow = newTableBody.insertRow(newTableBody.rows.length);
for (var i = 0; i < bodyDefine.length; i++)
{
var cell = tableRow.insertCell(i);
// テキスト設定
if (typeof bodyDefine[i].text !== 'undefined') {
var cellText;
if (typeof bodyDefine[i].text === 'function') {
cellText = bodyDefine[i].text(combatant, combatantIndex);
} else {
cellText = parseActFormat(bodyDefine[i].text, combatant);
}
cell.innerText = cellText;
} else if (typeof bodyDefine[i].html !== 'undefined') {
var cellHTML;
if (typeof bodyDefine[i].html === 'function') {
cellHTML = bodyDefine[i].html(combatant, combatantIndex);
} else {
cellHTML = parseActFormat(bodyDefine[i].html, combatant);
}
cell.innerHTML = cellHTML;
}
// 幅設定
cell.style.width = bodyDefine[i].width;
cell.style.maxWidth = bodyDefine[i].width;
// 行構え設定
if (typeof(bodyDefine[i].align) !== 'undefined') {
cell.style.textAlign = bodyDefine[i].align;
}
// エフェクト実行
if (typeof bodyDefine[i].effect === 'function') {
bodyDefine[i].effect(cell, combatant, combatantIndex);
}
}
combatantIndex++;
}
// tbody が既に存在していたら置換、そうでないならテーブルに追加
if (oldTableBody != void(0)) {
table.replaceChild(newTableBody, oldTableBody);
}
else {
table.appendChild(newTableBody);
}
}
// Miniparse フォーマット文字列を解析し、表示文字列を取得する
function parseActFormat(str, dictionary)
{
var result = "";
var currentIndex = 0;
do {
var openBraceIndex = str.indexOf('{', currentIndex);
if (openBraceIndex < 0) {
result += str.slice(currentIndex);
break;
}
else {
result += str.slice(currentIndex, openBraceIndex);
var closeBraceIndex = str.indexOf('}', openBraceIndex);
if (closeBraceIndex < 0) {
// parse error!
console.log("parseActFormat: Parse error: missing close-brace for " + openBraceIndex.toString() + ".");
return "ERROR";
}
else {
var tag = str.slice(openBraceIndex + 1, closeBraceIndex);
if (typeof dictionary[tag] !== 'undefined') {
result += dictionary[tag];
} else {
console.log("parseActFormat: Unknown tag: " + tag);
result += "ERROR";
}
currentIndex = closeBraceIndex + 1;
}
}
} while (currentIndex < str.length);
return result;
}
</script>
</head>
<body>
<div id="encounter">
No data to show.
<!-- ここにエンカウント情報が入る -->
</div>
<table id="combatantTable">
<!-- ここにヘッダが入る -->
<!-- ここに各キャラの情報が入る -->
</table>
</body>
</html>
The code you provided doesn't include any data, just the rendering algorithm. Without knowing what the data looks like, I can only guess based on what I can assume from the code. I can read the comments tho.
function parseActFormat(str, dictionary)
{
var result = "";
var currentIndex = 0;
do {
var openBraceIndex = str.indexOf('{', currentIndex);
if (openBraceIndex < 0) {
result += str.slice(currentIndex);
break;
}
else {
result += str.slice(currentIndex, openBraceIndex);
var closeBraceIndex = str.indexOf('}', openBraceIndex);
if (closeBraceIndex < 0) {
// parse error!
(...)
Just scanning this, it looks like a naive templating engine, for replacing I guess that part text: "{encdps}"
...
Also
var cell = tableRow.insertCell(i);
// テキスト設定
if (typeof bodyDefine[i].text !== 'undefined') {
var cellText;
if (typeof bodyDefine[i].text === 'function') {
cellText = bodyDefine[i].text(combatant, combatantIndex);
} else {
cellText = parseActFormat(bodyDefine[i].text, combatant);
}
cell.innerText = cellText;
From that part it seems that you can define the text as a function instead of a string, so try this:
{ text: function(combatant){ return Number(String(combatant.encdps)).toFixed(0); }, width: "20%", align: "right" },
In my example jsfidle you can see my doubt.
My jsfiddle
How do I get it to count the number of it and only appears to me once and not repeatedly.
My Html:
<section class="left" style="border-right:1px">
<div class="filter">
Pant Size
<div>
<div ng-repeat="professionalarea in pantsGroup">
<b><input type="checkbox" ng-model="usePants[professionalarea.description]"/>{{professionalarea.description}}</b>
<span>({{(filteredPlayers | filter:professionalarea).length}})</span>
</div>
</div>
</div>
</section>
My controller
$scope.$watch(function () {
return {
players: $scope.players,
usePants: $scope.usePants
}
}, function (value) {
var selected;
//here i want call professionalarea.description and don't pants
$scope.pantsGroup = uniqueItems($scope.players, 'professionalarea');
var filterAfterPants = [];
selected = false;
for (var j in $scope.players) {
var p = $scope.players[j];
for (var i in $scope.usePants) {
if ($scope.usePants[i]) {
selected = true;
if (i == p.professionalarea.description) {
filterAfterPants.push(p);
break;
}
}
}
}
if (!selected) {
filterAfterPants = $scope.players;
}
$scope.filteredPlayers = filterAfterPants;
}, true);
Example Image
Image
Added new function to get distinct items i.e. getDistinctValue
Please find following snippet..
(function () {
'use strict';
var myApp = angular.module('myApp', []);
var uniqueItems = function (data, key) {
var result = new Array();
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
console.log(value);
if (result.indexOf(value) == -1) {
result.push(value);
}
}
return result;
};
function getDistinctValue(items) {
var lookup = {};
var result = [];
for (var item, i = 0; item = items[i++];) {
var name = item.professionalarea.description;
if (!(name in lookup)) {
lookup[name] = 1;
result.push(name);
}
}
return result;
}
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function (file, uploadUrl) {
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
})
.success(function () {
})
.error(function () {
});
}
}]);
myApp.controller('myCtrl', ['$scope', function ($scope) {
$scope.usePants = {};
$scope.players = [
{
name: 'Bruce Wayne',
shirt: 'XXL',
pants: '42',
professionalarea: {
idAreaProfissional: 1,
description: "IT"
},
shoes: '12'
}, {
name: 'Bruce Wayne',
shirt: 'XXL',
pants: '28',
professionalarea: {
idAreaProfissional: 1,
description: "test"
},
shoes: '12'
}, {
name: 'Bruce Wayne',
shirt: 'XXL',
pants: '35',
professionalarea: {
idAreaProfissional: 1,
description: "IT"
},
shoes: '12'
}
];
// Watch the pants that are selected
$scope.$watch(function () {
return {
players: $scope.players,
usePants: $scope.usePants
}
}, function (value) {
var selected;
//here i want call professionalarea.description and don't pants
$scope.pantsGroup = getDistinctValue($scope.players);
var filterAfterPants = [];
selected = false;
for (var j in $scope.players) {
var p = $scope.players[j];
for (var i in $scope.usePants) {
if ($scope.usePants[i]) {
selected = true;
if (i == p.professionalarea.description) {
filterAfterPants.push(p);
break;
}
}
}
}
if (!selected) {
filterAfterPants = $scope.players;
}
$scope.filteredPlayers = filterAfterPants;
}, true);
$scope.$watch('filtered', function (newValue) {
if (angular.isArray(newValue)) {
console.log(newValue.length);
}
}, true);
}]);
myApp.filter('groupBy',
function () {
return function (collection, key) {
if (collection === null) return;
return uniqueItems(collection, key);
};
});
})();
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="app.js" type="text/javascript"></script>
<style>
.gridStyle {
border: 1px solid rgb(212, 212, 212);
margin-left: 15px;
width: 97%;
height: 130px;
float: left;
font-weight: normal;
padding: 35px 10px 10px 10px;
}
</style>
<title>Upload </title>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<div>
<section class="left" style="border-right:1px">
<div class="filter">
Pant Size
<div>
<div ng-repeat="professionalarea in pantsGroup">
<b><input type="checkbox" ng-model="usePants[professionalarea]" />{{professionalarea}}</b>
<span>({{filteredPlayers.length}})</span>
</div>
</div>
</div>
</section>
<section class="right" style="border-right:1px">
<div>
<ul>
<li ng-repeat="player in filteredPlayers | filter:query">
<p><b>Player: {{player.name}}</b></p>
<p>Shirt Size: {{player.shirt}} Pant Size: {{player.pants}} Shoe Size: {{player.shoes}}</p>
</li>
</ul>
</div>
</section>
</div>
</div>
</body>
</html>
Now, I have tow buttons. The first button named "array1", the other button named 'array2'. I have an array called "newArray." I have an array named "array1". I have an array named "array2".I have an array called "unselectedArray."
When I click the array1 button, I want to show the item in array1, but the item is not in "newArray1". When I click the array2 button, I want to show the item in array2, but the item is not in "newArray1" This show array is "unselectedArray."
When I click the item in the "unselectedArray," the item is added in 'newArrray';
I use two hours to solve it, but I haven't written the right code.
This is my code:
<style>
.bigDiv {
width: 500px; height: 100%;
margin: 60px auto; background-color: red;
}
li {
float: left;
width: 50px; height: 50px;
}
.selected,.buttonArea,.unselected {
height: 100px;
}
</style>
<div class="bigDiv">
<div class="selected">
<ul>
<li ng-repeat="item in newArray">
{{item.text}}
</li>
</ul>
</div>
<div class="buttonArea">
<button ng-click="showArrayFun('array1')">array1</button>
<button ng-click="showArrayFun('array2')">array2</button>
</div>
<div class="unselected">
<ul>
<li ng-click="addToNewArrayFun($index)" ng-repeat="item in unselectedArray">
{{item.text}}
</li>
</ul>
</div>
</div>
angular.module('myApp', []).controller('con', function ($scope) {
$scope.array1 = [
{
id: 11,
text: 'one'
},
{
id: 12,
text: 'two'
},
];
$scope.array2 = [
{
id: 21,
text: 'winter'
},
{
id: 22,
text: 'spring'
},
];
$scope.newArray = [
{
id: 12,
text: 'two'
}
];
$scope.unselectedArray = [];
$scope.addToNewArrayFun = function (index) {
$scope.newArray.push($scope.unselectedArray[index]);
};
$scope.showArrayFun = function (arrayName) {
if (arrayName == 'array1') {
$scope.unselectedArray = $scope.array1.filter(function (item) {
console.log(($scope.newArray.indexOf(item) == -1));
return ( ($scope.newArray.indexOf(item) == -1) == true );
});
} else if (arrayName == 'array2') {
$scope.unselectedArray = $scope.array2.filter(function (item) {
console.log(($scope.newArray.indexOf(item) == -1));
return ( ($scope.newArray.indexOf(item) == -1) == true );
});
}
}
}
);
Why my code not work? Who can correct my code?
Please write the code which is using $filter.
Who can create AngularJS custom filters to realize it.
// Code goes here
angular.module('myApp', []).controller('con', function ($scope) {
$scope.array1 = [
{
id: 11,
text: 'one'
},
{
id: 12,
text: 'two'
},
];
$scope.array2 = [
{
id: 21,
text: 'winter'
},
{
id: 22,
text: 'spring'
},
];
$scope.newArray = [
{
id: 12,
text: 'two'
}
];
$scope.unselectedArray = [];
$scope.addToNewArrayFun = function (index) {
$scope.newArray.push($scope.unselectedArray[index]);
$scope.unselectedArray.splice(index, 1);
};
$scope.showArrayFun = function (arrayName) {
if (arrayName == 'array1') {
$scope.unselectedArray = $scope.array1.filter(function (item) {
return ( ($scope.newArray.indexOf(item) == -1));
});
} else if (arrayName == 'array2') {
$scope.unselectedArray = $scope.array2.filter(function (item) {
return ( ($scope.newArray.indexOf(item) == -1));
});
}
};
})
/* Styles go here */
.bigDiv {
width: 500px; height: 100%;
margin: 60px auto;
background-color: red;
}
li {
float: left;
width: 50px; height: 50px;
}
.selected,.buttonArea,.unselected {
height: 100px;
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body ng-controller="con">
<div class="bigDiv">
<div class="selected">
<ul>
<li ng-repeat="item in newArray">
{{item.text}}
</li>
</ul>
</div>
<div class="buttonArea">
<button ng-click="showArrayFun('array1')">array1</button>
<button ng-click="showArrayFun('array2')">array2</button>
</div>
<div class="unselected">
<ul>
<li ng-click="addToNewArrayFun($index)" ng-repeat="item in unselectedArray">
{{item.text}}
</li>
</ul>
</div>
</div>
</body>
</html>
<div class="bigDiv">
<div class="selected">
<ul>
<li ng-click=" deleteItemFun($index)" ng-repeat="item in newArray track by $index ">
{{item.text}}
</li>
</ul>
</div>
<div class="buttonArea">
<button ng-click="showArrayFun('array1')">array1</button>
<button ng-click="showArrayFun('array2')">array2</button>
</div>
<div class="unselected">
<ul>
<li ng-click="addToNewArrayFun($index)" ng-repeat="item in unselectedArray | fiArray : newArray ">
{{item.text}}
</li>
</ul>
</div>
</div>
angular.module('myApp', []).filter('fiArray', function () {
return function (array, aimArray) {
var tempArray = array;
if (tempArray.length == 0)
return [];
for (var i = 0; i < aimArray.length; i++) {
for (var j = 0; j < tempArray.length; j++) {
if (tempArray[j].id === aimArray[i].id) {
tempArray.splice(j, 1);
j--;
break;
}
}
}
return tempArray;
}
})
.controller('con', ['$scope', 'fiArrayFilter', function ($scope, fiArrayFilter) {
$scope.newArray = [
{
id: 12,
text: 'two'
}
];
$scope.array1 = [
{
id: 11,
text: 'one'
},
{
id: 12,
text: 'two'
},
];
$scope.array2 = [
{
id: 21,
text: 'winter'
},
{
id: 22,
text: 'spring'
},
];
$scope.unselectedArray = [];
$scope.addToNewArrayFun = function (index) {
$scope.newArray.push($scope.unselectedArray[index]);
};
$scope.deleteItemFun = function (index) {
$scope.newArray.splice(index, 1)
}
$scope.showArrayFun = function (arrayName) {
var copyArr = [];
if (arrayName == 'array1') {
copyArr = $scope.array1.concat();
}
else if (arrayName == 'array2') {
copyArr = $scope.array2.concat();
}
$scope.unselectedArray = copyArr;
}
}])
;
I have taken about 6 runs at this and while I can get many PARTS of it working, I can't seem to get everything functioning like I want it to. This is the latest attempt. This was originally written with just JavaScript but as an exercise I am trying to change it to AngularJS.
Template normal.html:
<section id="container" class="container panels-backface-invisible" >
<div id="carousel" class="panels-backface-invisible 3rows">
<figure ng-repeat="movie in movies.data | filterMultiple:{genres:genList,wildcard:wcSearch}" class="folder figure"
style="transform: {{carousel.rotateFn}}({{carousel.theta*$index}}deg) translateZ({{carousel.radius}}px);" >
</figure></div>
</section>
<div class="searchbox"><label>Wildcard Title Search</label><input type="text" style="width: 100px;" ng-model="wcSearch">
</div>
<div style="display: inline-block;
position: absolute;
right: 8%;
bottom: 1px;
width: 15%;"
multi-select
input-model="genreList"
button-label="name"
item-label="icon"
tick-property="ticked"
selection-mode="multiple"
helper-elements=""
on-open="msOpen( data )"
on-close="msClose( data )"
on-item-click="msClick( data )"
>
</div>
app.js:
angular.module('MovieCarousel', ['ui.router','multi-select'])
.config(function config($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/');
$stateProvider.state("index",{
url:"",
controller:"MovieFlowCtrl",
templateUrl:"templates/normal.html",
resolve:{
movieData: function($http){
var promise = $http.get('moviedata.php').
success(function(data) {
var mData={};
mData.count = data.length*2;
mData.data = data;
return mData;
});
return promise;
}
}
})
$stateProvider.state("new",{
url:"/New",
controller:"MovieFlowCtrl",
templateUrl:"templates/New.html",
resolve:{
movieData: function($http){
var promise = $http.get('moviedata.php?type=N').
success(function(data) {
var mData={};
mData.count = data.length*2;
mData.data = data;
return mData;
});
return promise;
}
}
})
})
.controller('MovieFlowCtrl', function ($scope, $rootScope, movieData, $filter) {
$scope.carousel = {};
$scope.carousel.isHorizontal = true;
$scope.movies = movieData;
$scope.carousel.element = document.getElementById('carousel');
setTimeout( function(){
document.body.addClassName('ready');
}, 0);
$scope.clearSelection=function() {
$rootScope.genrefilter = [];
$('#selectable .ui-selected').removeClass('ui-selected');
}
$rootScope.genrefilter = [];
$scope.msClick = function(Data) {
console.log(Data);
var selectedind = $rootScope.genrefilter.indexOf(Data.name);
if(selectedind>=0){
$rootScope.genrefilter.splice(selectedind,1);
}
else{
$rootScope.genrefilter.push(Data.name);
}
$scope.carousel.filter();
// $filter('filterMultiple');
}
$rootScope.genreList = [
{ icon: "<img src=/img/Action.png />", name: "Action", ticked: false },
{ icon: "<img src=/img/Adventure.png>", name: "Adventure", ticked: false },
{ icon: "<img src=/img/Animation.png>", name: "Animation", ticked: false },
{ icon: "<img src=/img/Biography.png />", name: "Biography", ticked: false },
{ icon: "<img src=/img/Comedy.png />", name: "Comedy", ticked: false },
{ icon: "<img src=/img/Comic-Book.png />", name: "Comic-Book", ticked: false },
{ icon: "<img src=/img/Crime.png>", name: "Crime", ticked: false },
{ icon: "<img src=/img/Disaster.png />", name: "Disaster", ticked: false },
{ icon: "<img src=/img/Drama.png />", name: "Drama", ticked: false },
{ icon: "<img src=/img/Fantasy.png />", name: "Fantasy", ticked: false },
{ icon: "<img src=/img/History.png>", name: "History", ticked: false },
{ icon: "<img src=/img/Horror.png>", name: "Horror", ticked: false },
{ icon: "<img src=/img/Music.png />", name: "Music", ticked: false },
{ icon: "<img src=/img/Musical.png />", name: "Musical", ticked: false },
{ icon: "<img src=/img/Mystery.png />", name: "Mystery", ticked: false },
{ icon: "<img src=/img/Romance.png>", name: "Romance", ticked: false },
{ icon: "<img src=/img/Sci-Fi.png />", name: "Sci-Fi", ticked: false },
{ icon: "<img src=/img/Sport.png />", name: "Sport", ticked: false },
{ icon: "<img src=/img/Thriller.png />", name: "Thriller", ticked: false },
{ icon: "<img src=/img/War.png>", name: "War", ticked: false },
{ icon: "<img src=/img/Western.png />", name: "Western", ticked: false }
];
$scope.msOpen = function( data ) {
console.log("open");
draglock = 1;
}
$scope.msClose = function( data ) {
console.log("closed");
draglock = 0; }
$rootScope.modify = function(){
if(wheight>=930){
sz1=300;
sz2=2.4;
}
else if(wheight>700 && wheight<929) {
sz1=283;
sz2= 3;
}
else if(wheight>500 && wheight<699) {
sz1=221;
sz2= 3.8;
}
else if(wheight>400 && wheight<499) {
sz1=157;
sz2=5.2;
}
else{
sz1=125;
sz2=6.6;
}
console.log("Modify");
// sz1 = $(window).width()*0.19;
panelCount = $rootScope.panelCount;
$scope.carousel.sz1 = sz1;
$scope.carousel.panelSize = sz1;
// if(typeof $scope.carousel.element.children[0] != 'undefined'){$scope.carousel.panelSize = $scope.carousel.element.children[0].clientWidth;}
$scope.carousel.rotateFn = $scope.carousel.isHorizontal ? 'rotateY' : 'rotateX';
// console.log(panelCount);
$scope.carousel.theta = 359 / ((panelCount+mrows));
theta = $scope.carousel.theta;
rotateXY = $scope.carousel.rotateFn;
var sizeadj = 12;
if(mrows == 1){sizeadj = 0.8;}
if(mrows == 2){sizeadj = sz2;}
$scope.carousel.radius = ($scope.carousel.panelSize*(mrows+panelCount/mrows))/(2*Math.PI); //Math.round(( $scope.carousel.panelSize/sizeadj) / Math.tan( Math.PI / (($scope.carousel.panelCount+mrows)) ) );
radius = $scope.carousel.radius;
$scope.carousel.rotation = Math.round( $scope.carousel.rotation / $scope.carousel.theta ) * $scope.carousel.theta;
rotation = $scope.carousel.rotation;
$scope.carousel.rotation = -4;
$scope.carousel.element.style[ transformProp ] = 'translateZ(-' + radius + 'px) ' + rotateXY + '(' + rotation + 'deg)';
// if(typeof $scope.carousel.element.children[0] != 'undefined'){$scope.carousel.sz1 = $scope.carousel.element.children[0].clientWidth;}
}
$scope.doubleClick = function(movieName){
console.log("test");
jQuery.post("/processrequest.php",
{name: movieName },
function(response){
if(response.length>5){alert(response);}
});
}
$rootScope.toggleCarousel = function(toMod){
panelCount = $rootScope.panelCount;
console.log("toggleCarousel");
if(toMod){return;}
if(panelCount > 20){
$('#container').addClass('container');
$('figure').addClass('figure');
filtered = 0;
$rootScope.modify(panelCount);
}
else{
$('figure').attr('style', '');
$('#carousel').attr('style', 'transform: translate(0px,0px)');
$('#container').removeClass('container');
$('figure').removeClass('figure');
filtered = 1;
}
$scope.carousel.element.style[ transformProp ] = 'translateZ(-' + radius + 'px) ' + rotateXY + '(' + rotation + 'deg)';
}
})
.directive('myDraggable', ['$document', function($document) {
return function(scope, element, attr) {
var startX = 0, startY = 0, x = 0, y = 0;
element.css({
position: 'relative',
border: '1px solid red',
backgroundColor: 'lightgrey',
cursor: 'pointer'
});
element.on('mousedown', function(event) {
// Prevent default dragging of selected content
event.preventDefault();
startX = event.pageX - x;
startY = event.pageY - y;
$document.on('mousemove', mousemove);
$document.on('mouseup', mouseup);
});
function mousemove(event) {
y = event.pageY - startY;
x = event.pageX - startX;
element.css({
top: y + 'px',
left: x + 'px'
});
}
function mouseup() {
$document.off('mousemove', mousemove);
$document.off('mouseup', mouseup);
}
};
}])
.filter('filterMultiple',["$rootScope", '$filter', function ($rootScope,$filter) {
return function (items, keyObj) {
var wcSearch = keyObj.wildcard;
var genres = keyObj.genres;
var filterObj=[];
for(var i=0;i<items.length;i++){
var filtered = true;
if(typeof wcSearch === 'undefined'){}
else if(wcSearch.length > 0){
if(wcSearch.toUpperCase().substring(0,wcSearch.length) != items[i].title.toUpperCase().substring(0,wcSearch.length) && wcSearch.toUpperCase().substring(0,wcSearch.length) != items[i].sortTitle.toUpperCase().substring(0,wcSearch.length)){filtered = false;}
}
if(filtered == true){
for(var x=0;x<$rootScope.genrefilter.length;x++){
if(items[i].genres.indexOf($rootScope.genrefilter[x])<0){filtered = false;}
}
}
if(filtered == true){
filterObj.push(items[i]);
}
}
*******Disabled due to infinite loop
// var ticked=[];
// var genreObj={};
// var $tempGenre=[];
// $tempGenre.genreList = $rootScope.genreList;
// for (var i=0;i<$tempGenre.genreList.length;i++){
// ticked[$tempGenre.genreList[i].name]=$tempGenre.genreList[i].ticked;
// }
// $tempGenre.genreList=[];
// if(typeof filterObj !== 'undefined'){
// for (var i=0;i<filterObj.length;i++){
// for (var z=0;z<filterObj[i].genres.length;z++){
// if($tempGenre.genreList.map(function(e) { return e.name; }).indexOf(filterObj[i].genres[z])==-1)
// {
// if(filterObj[i].genres[z] !=""){
// genreObj = {icon: "<img src=/img/"+filterObj[i].genres[z]+".png />", name: filterObj[i].genres[z], ticked: ticked[filterObj[i].genres[z]] };
// $tempGenre.genreList.push(genreObj);
// }
// }
// }
// }
// }
// $tempGenre.genreList.sort();
var toModify=false;
if($rootScope.panelCount == filterObj.length){toModify=true;}
console.log($rootScope.panelCount+","+filterObj.length);
$rootScope.panelCount = filterObj.length;
$rootScope.toggleCarousel(toModify);
$rootScope.genreList = $tempGenre;
return filterObj;
}
}])
.filter('unique', function() {
return function(input, key) {
var unique = {};
var uniqueList = [];
for(var i = 0; i < input.length; i++){
if(typeof unique[input[i][key]] == "undefined"){
unique[input[i][key]] = "";
uniqueList.push(input[i]);
}
}
return uniqueList;
};
})
.directive('resize', function($window) {
return function (scope, element, attr) {
var w = angular.element($window);
scope.$watch(function () {
return {
'h': w.height(),
'w': w.width()
};
}, function (newValue, oldValue) {
scope.windowHeight = newValue.h;
scope.windowWidth = newValue.w;
scope.resizeWithOffset = function (offsetH) {
scope.$eval(attr.notifier);
return {
'height': (newValue.h - offsetH) + 'px'
};
};
}, true);
w.bind('resize', function () {
scope.$apply();
});
}
})
Obviously I'm very new to AngularJS and am likely doing everything wrong. I have searched for similar solutions to learn from but can't find anything that is doing quite what I'm working on. The main issue I am having at this point is if I include the code that limits genres to only those available in the sub-set of movie results it loops infinitely, and no matter which angle I take I can't seem to get it all to work together. Some guidance would be greatly appreciated, even if its just to recommend a better structure, I'm sure I'm putting too much into the controller among other fails.
Other unfinished portions:
- views for each type of content
- re-size elements on window size
- Drag and scroll behavior
EDIT Here is my drop down list from the view-
<div class="ToolBox" style="height: 30px; width: 100%">
<b> Sort By: </b>
<select id="ddlSortBy" style="margin-top: 0px; height: 24px; width: 160px !important"
data-bind="value: serverSelectedOptionID, options: serverOptions, optionsText: 'name', optionsValue: 'id'">
</select> <img data-bind="click: SortUpDownAllCerts" src="/Content/images/updownarrow.bmp" style="padding-bottom: 4px; cursor: pointer; vertical-align: middle;" />
</div>
In my view, I am displaying the length of an observableArray-
My Certificates (<span data-bind="text: allCertificates().length"></span>)
If I sort the observableArray using the below code, the length of the allCertificates observableArray shows 0 (66 records do display on the screen, so the length of the observableArray should be 66)-
serverSelectedOptionID.subscribe(function () {
var sortCriteriaID = serverSelectedOptionID._latestValue;
allCertificates.sort(function (a, b) {
var fieldname = serverOptions[sortCriteriaID-1].OptionText;
allCertificates.valueHasMutated();
if (a[fieldname] == b[fieldname]) {
return a[fieldname] > b[fieldname] ? 1 : a[fieldname] < b[fieldname] ? -1 : 0;
}
return a[fieldname] > b[fieldname] ? 1 : -1;
});
});
If I comment out the above code, the allCertificates observableArray shows 66 as the length just like it should.
For completeness, here is the entire viewmodel code-
define(['services/logger', 'durandal/system', 'durandal/plugins/router', 'services/CertificateDataService'],
function (logger, system, router, CertificateDataService) {
var allCertificates = ko.observableArray([]);
var myCertificates = ko.observableArray([]);
var serverSelectedOptionID = ko.observableArray();
var serverOptions = [
{ id: 1, name: 'Certificate', OptionText: 'lwCertID' },
{ id: 2, name: 'Client Name', OptionText: 'clientName' },
{ id: 3, name: 'Client Number', OptionText: 'clientNumber' },
{ id: 4, name: 'Request Date', OptionText: 'requestDate' },
{ id: 5, name: 'Collateral Analyst', OptionText: 'userName' }
];
var serverSelectedOptionID = ko.observable();
var activate = function () {
// go get local data, if we have it
return SelectAllCerts(), SelectMyCerts();
};
var vm = {
activate: activate,
allCertificates: allCertificates,
myCertificates: myCertificates,
title: 'Certificate Approvals',
SelectMyCerts: SelectMyCerts,
SelectAllCerts: SelectAllCerts,
theOptionId: ko.observable(1),
serverOptions: serverOptions,
serverSelectedOptionID: serverSelectedOptionID
};
serverSelectedOptionID.subscribe(function () {
var sortCriteriaID = serverSelectedOptionID._latestValue;
allCertificates.sort(function (a, b) {
var fieldname = serverOptions[sortCriteriaID-1].OptionText;
allCertificates.valueHasMutated();
if (a[fieldname] == b[fieldname]) {
return a[fieldname] > b[fieldname] ? 1 : a[fieldname] < b[fieldname] ? -1 : 0;
}
return a[fieldname] > b[fieldname] ? 1 : -1;
});
});
function getFieldNameByOptionID(OptionID) {
}
return vm;
function SortUpDownAllCerts() {
return allCertificates.sort()
}
function SortUpDownMyCerts() {
return allCertificates.sort()
}
function SelectAllCerts() {
return CertificateDataService.getallCertificates(allCertificates);
}
function SelectMyCerts() {
return CertificateDataService.getMyCertificates(myCertificates);
}
});
How can I get this to work? Why does it evaluate to 0 and not 66?
You are going to hate yourself for this -
http://jsfiddle.net/VzER2/15/
The only problem in your code was this
<h2 data-bind="text: title()"></h2>Length: <span data-bind="text: allCertificates().length"></span>
You had allCertificates.length instead of allCertificates().length. When you are in the view and using a data-bind it unwraps your observable for you. But if you need to get a property of that observable you need to call it again.
If there is something else that is not working let me know, I haven't tried changing the value of serverSelectedID