AngularJS image carousel with filter - javascript

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

Related

JavaScript var object perfom function on attribute

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" },

Passing data into chart using HTML and JavaScript

The following code is used to display a chart. The problem is the "data" is hard coded in. How can I change this so that the chart displays values which are displayed using:
<div id="name"> </div>
<div id="testscore"></div>
The above 2 div's contain dynamic values. I want to display these values in the chart.
<script type="text/javascript">
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer",
{
// title:{
// text: "Olympic Medals of all Times (till 2012 Olympics)"
// },
animationEnabled: true,
legend: {
cursor:"pointer",
itemclick : function(e) {
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
}
else {
e.dataSeries.visible = true;
}
chart.render();
}
},
axisY: {
title: "Time"
},
toolTip: {
shared: true,
content: function(e){
var str = '';
var total = 0 ;
var str3;
var str2 ;
for (var i = 0; i < e.entries.length; i++){
var str1 = "<span style= 'color:"+e.entries[i].dataSeries.color + "'> " + e.entries[i].dataSeries.name + "</span>: <strong>"+ e.entries[i].dataPoint.y + "</strong> <br/>" ;
total = e.entries[i].dataPoint.y + total;
str = str.concat(str1);
}
str2 = "<span style = 'color:DodgerBlue; '><strong>"+e.entries[0].dataPoint.label + "</strong></span><br/>";
str3 = "<span style = 'color:Tomato '>Total: </span><strong>" + total + "</strong><br/>";
return (str2.concat(str)).concat(str3);
}
},
data: [
{
type: "bar",
showInLegend: true,
name: "Black",
color: "#000000",
dataPoints: [
{ y: 0.18, label: "Name"},
{ y: 0.12, label: "Name 1"},
{ y: 0.59, label: "Name 2"},
{ y: 1.15, label: "Name 3"},
]
},
]
});
chart.render();
}
</script>
You can simply call
var data = document.getElementById('name').value;
var data2 = document.getElementById('testscore').value;
If it's a single value, it would work; otherwise, you need to do it this way:
var array = $('#your.id').data('stuff');
Here, "stuff" is nothing but
<div data-stuff="some data" ></div>
Or, create an array by:
var array = new Array();
and finally, store the data into the array.

How to create extension to curve texts in svg-edit?

I want to use svg-edit plugin in my project. Now I want to create extension to curve texts like:
svgEditor.addExtension("Curve text!", function() {'use strict';
return {
name: "Curve text",
svgicons: svgEditor.curConfig.extPath + "text_curve-icon.xml",
buttons: [{
id: "text_curve",
type: "mode",
title: "Curve the text",
events: {
'click': function() {
svgCanvas.setMode("text_curve");
var textElement = $(svgCanvas.getSelectedElems()[0]);
var textPath = '<text>' +
' <textPath xlink:href="#relativeCurve">' +
$(svgCanvas.getSelectedElems()[0]).text() +
' </textPath>' +
'</text>';
$('#svgcontent').prepend('<defs><path d="m0,350c100,-100 200,-200 300,-200c100,0 200,200 300,200c100,0 200,-200 300,-200" id="relativeCurve"/></defs>');
$(textElement).replaceWith(textPath);
}
}
}],
mouseDown: function() {
if(svgCanvas.getMode() == "text_curve") {
return {started: true};
}
},
mouseUp: function(opts) {
if(svgCanvas.getMode() == "text_curve") {
}
}
};
});
But it doesn't work, how can I create this?

Kendo TreeView Search with Highlight

I have a KendoTreeview with spriteclass. I want to highlight the nodes (root as well as child nodes) with my search term. I have implemented the search functionality. But the issue when i search it is highlighting the term in the nodes but missing the SpriteClass in the nodes after first search. Any idea ?
jsFiddle code
$('#search-term').on('keyup', function () {
$('span.k-in > span.highlight').each(function () {
$(this).parent().text($(this).parent().text());
});
// ignore if no search term
if ($.trim($(this).val()) == '') {
return;
}
var term = this.value.toUpperCase();
var tlen = term.length;
$('#treeview-sprites span.k-in').each(function (index) {
var text = $(this).text();
var html = '';
var q = 0;
while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
q = p + tlen;
}
if (q > 0) {
html += text.substring(q);
$(this).html(html);
$(this).parentsUntil('.k-treeview').filter('.k-item').each(
function (index, element) {
$('#treeview-sprites').data('kendoTreeView').expand($(this));
$(this).data('search-term', term);
});
}
});
$("#treeview-sprites").kendoTreeView({
dataSource: [{
text: "My Documents",
expanded: true,
spriteCssClass: "rootfolder",
items: [{
text: "Kendo UI Project",
expanded: true,
spriteCssClass: "folder",
items: [{
text: "about.html",
spriteCssClass: "html"
}, {
text: "index.html",
spriteCssClass: "html"
}, {
text: "logo.png",
spriteCssClass: "image"
}]
}, {
text: "New Web Site",
expanded: true,
spriteCssClass: "folder",
items: [{
text: "mockup.jpg",
spriteCssClass: "image"
}, {
text: "Research.pdf",
spriteCssClass: "pdf"
}, ]
}, {
text: "Reports",
expanded: true,
spriteCssClass: "folder",
items: [{
text: "February.pdf",
spriteCssClass: "pdf"
}, {
text: "March.pdf",
spriteCssClass: "pdf"
}, {
text: "April.pdf",
spriteCssClass: "pdf"
}]
}]
}]
})
;
Kendo's tree view widget doesn't like it if you muck around in its HTML, so I suggest modifying the data source instead (this will require the encoded option for all items in the DS).
In the keyup handler, you reset the DS whenever you search to clear highlighting, then instead of replacing the element's HTML directly, you set the model's text property:
$('#search-term').on('keyup', function () {
var treeView = $("#treeview-sprites").getKendoTreeView();
treeView.dataSource.data(pristine);
// ignore if no search term
if ($.trim($(this).val()) == '') {
return;
}
var term = this.value.toUpperCase();
var tlen = term.length;
$('#treeview-sprites span.k-in').each(function (index) {
var text = $(this).text();
var html = '';
var q = 0;
while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
q = p + tlen;
}
if (q > 0) {
html += text.substring(q);
var dataItem = treeView.dataItem($(this));
dataItem.set("text", html);
$(this).parentsUntil('.k-treeview').filter('.k-item').each(
function (index, element) {
$('#treeview-sprites').data('kendoTreeView').expand($(this));
$(this).data('search-term', term);
});
}
});
$('#treeview-sprites .k-item').each(function () {
if ($(this).data('search-term') != term) {
$('#treeview-sprites').data('kendoTreeView').collapse($(this));
}
});
});
The tree definition needs the encoded option for this to work:
var pristine = [{
encoded: false,
text: "Kendo UI Project",
expanded: true,
spriteCssClass: "folder",
items: [{
encoded: false,
text: "about.html",
spriteCssClass: "html"
}, {
encoded: false,
text: "index.html",
spriteCssClass: "html"
}, {
encoded: false,
text: "logo.png",
spriteCssClass: "image"
}]
}, {
encoded: false,
text: "New Web Site",
expanded: true,
spriteCssClass: "folder",
items: [{
encoded: false,
text: "mockup.jpg",
spriteCssClass: "image"
}, {
encoded: false,
text: "Research.pdf",
spriteCssClass: "pdf"
}, ]
}, {
encoded: false,
text: "Reports",
expanded: true,
spriteCssClass: "folder",
items: [{
encoded: false,
text: "February.pdf",
spriteCssClass: "pdf"
}, {
encoded: false,
text: "March.pdf",
spriteCssClass: "pdf"
}, {
encoded: false,
text: "April.pdf",
spriteCssClass: "pdf"
}]
}];
$("#treeview-sprites").kendoTreeView({
dataSource: [{
text: "My Documents",
expanded: true,
spriteCssClass: "rootfolder",
items: pristine
}]
});
(demo)
Good job guys, just what I neeeded!
Using your code I did a small tweak (actually added just two lines of jquery filtering), so that now when searching for a keyword, the treeview shows only the branches that contain highlighted texts. Easy peasy! :)
Other branches are hidden if they do not contain the higlighted text. Simple as that.
This means we now have a VisualStudio-like treeview search (see the Visual Studio Solution Explorer Search and Filter: http://goo.gl/qr7yVb).
Here's my code and demo on jsfiddle: http://jsfiddle.net/ComboFusion/d0qespaz/2/
HTML:
<input id="treeViewSearchInput"></input>
<ul id="treeview">
<li data-expanded="true">My Web Site
<ul>
<li data-expanded="true">images
<ul>
<li>logo.png</li>
<li>body-back.png</li>
<li>my-photo.jpg</li>
</ul>
</li>
<li data-expanded="true">resources
<ul>
<li data-expanded="true">pdf
<ul>
<li>brochure.pdf</li>
<li>prices.pdf</li>
</ul>
</li>
<li>zip</li>
</ul>
</li>
<li>about.html</li>
<li>contacts.html</li>
<li>index.html</li>
<li>portfolio.html</li>
</ul>
</li>
<li>Another Root</li>
</ul>
CSS
span.k-in > span.highlight {
background: #7EA700;
color: #ffffff;
border: 1px solid green;
padding: 1px;
}
JAVASCRIPT
function InitSearch(treeViewId, searchInputId) {
var tv = $(treeViewId).data('kendoTreeView');
$(searchInputId).on('keyup', function () {
$(treeViewId + ' li.k-item').show();
$('span.k-in > span.highlight').each(function () {
$(this).parent().text($(this).parent().text());
});
// ignore if no search term
if ($.trim($(this).val()) === '') {
return;
}
var term = this.value.toUpperCase();
var tlen = term.length;
$(treeViewId + ' span.k-in').each(function (index) {
var text = $(this).text();
var html = '';
var q = 0;
var p;
while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
q = p + tlen;
}
if (q > 0) {
html += text.substring(q);
$(this).html(html);
$(this).parentsUntil('.k-treeview').filter('.k-item').each(function (index, element) {
tv.expand($(this));
$(this).data('SearchTerm', term);
});
}
});
$(treeViewId + ' li.k-item:not(:has(".highlight"))').hide();
$(treeViewId + ' li.k-item').expand(".k-item");
});
}
var $tv = $("#treeview").kendoTreeView();
InitSearch("#treeview", "#treeViewSearchInput");
Another tweak from me :)
What I did was change the highlight code in order to preserve anything else that might exist in the node html (such as sprite span for example).
I also implemented it as a TypeScript class wrapper around the TreeView.
If you don't want TypeScript stuff just copy the code out and it should work fine :)
export class SearchableTreeView {
TreeView: kendo.ui.TreeView;
emphasisClass: string;
constructor(treeView: kendo.ui.TreeView) {
this.TreeView = treeView;
this.emphasisClass = "bg-warning";
}
search(term: string): void {
var treeElement: JQuery = this.TreeView.element;
var tv: kendo.ui.TreeView = this.TreeView;
var emphClass = this.emphasisClass;
this.resetHighlights();
// ignore if no search term
if ($.trim(term) === '') { return; }
var term = term.toUpperCase();
var tlen = term.length;
$('span.k-in', treeElement).each(function (index) {
// find all corresponding nodes
var node = $(this);
var htmlContent = node.html();
var text = node.text();
var searchPosition = text.toUpperCase().indexOf(term);
if (searchPosition === -1) {
// continue
return true;
}
var generatedHtml = '<span class="highlight-container">' + text.substr(0, searchPosition) + '<span class="' + emphClass + '">' + text.substr(searchPosition, tlen) + '</span>' + text.substr(searchPosition + tlen) + '</span>';
htmlContent = htmlContent.replace(text, generatedHtml);
node.html(htmlContent);
node.parentsUntil('.k-treeview').filter('.k-item').each(
function (index, element) {
tv.expand($(this));
$(this).data('search-term', term);
}
);
});
$('.k-item', treeElement).each(function () {
if ($(this).data('search-term') != term) {
tv.collapse($(this));
}
});
}
resetHighlights(): void {
this.TreeView.element.find("span.k-in:has('." + this.emphasisClass + "')")
.each(function () {
var node = $(this);
var text = node.text();
$(".highlight-container", node).remove();
node.append(text);
});
}
}
$("#textBox").on("input", function () {
var query = this.value.toLowerCase();
var dataSource = $("#Treeview").data("kendoTreeView").dataSource;
filter(dataSource, query);
});
function filter(dataSource, query) {
var uidData = [];
var data = dataSource instanceof kendo.data.DataSource && dataSource.data();
for (var i = 0; i < data.length; i++) {
var item = data[i];
var text = item.text.toLowerCase();
var isChecked = item.checked;
var itemVisible =
query === true
|| query === ""
|| text.indexOf(query) >= 0;
uidData.push({ UID: item.uid, Visible: itemVisible });
}
if (query != "") {
$.each(uidData, function (index, datavalue) {
if (datavalue.Visible) {
$("li[data-uid='" + datavalue.UID + "']").addClass("highlight");
}
else {
$("li[data-uid='" + datavalue.UID + "']").removeClass("highlight");
}
});
}
else {
$.each(uidData, function (index, datavalue) {
$("li[data-uid='" + datavalue.UID + "']").removeClass("highlight");
});
}
}
CSS :
.highlight {
background:#0fa1ba;
color:white;
}
For Angular 2+ you need to create a pipe for this feature.
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
import { NGXLogger } from 'ngx-logger';
#Pipe({
name: 'highlight'
})
export class TypeaheadHighlight implements PipeTransform {
constructor(private readonly _sanitizer: DomSanitizer, private readonly logger: NGXLogger) { }
transform(matchItem: any, query: any): string {
let matchedItem: any;
if (matchItem) {
matchedItem = matchItem.toString();
}
if (this.containsHtml(matchedItem)) {
this.logger.warn('Unsafe use of typeahead please use ngSanitize');
}
matchedItem = query ? ('' + matchedItem).replace(new RegExp(this.escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchedItem; // Replaces the capture string with a the same string inside of a "strong" tag
if (!this._sanitizer) {
matchedItem = this._sanitizer.bypassSecurityTrustHtml(matchedItem);
}
return matchedItem;
}
escapeRegexp = (queryToEscape) => queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
containsHtml = (matchItem) => /<.*>/g.test(matchItem);
}
Use of this pipe in html template....
<input name="searchTerm" type="text" [(ngModel)]="searchTerm" (keyup)='onkeyup(searchTerm)'
/>
</div>
<div style="height: 70vh;overflow: auto">
<kendo-treeview style="margin-top: 50px" id="availableColumns" [nodes]="availableColumns"
textField="displayName" kendoTreeViewExpandable kendoTreeViewFlatDataBinding idField="id"
parentIdField="parentId">
<ng-template kendoTreeViewNodeTemplate let-dataItem>
<span [tooltip]="dataItem.columnDescription"
[innerHtml]="dataItem.displayName | highlight:searchTerm "></span>
</ng-template>
</kendo-treeview>
</div>

Creating Toolbar In Extjs 4.2 which should like Stack Overflow Toolbar

Am Creating Toolbar Which Is like Stack Overflow having Like This Am Creating Please Go Down you will see Pagination.Now Am stack in between how processed futhure .
i have created 4 buttons which are current page, its next page, and second and last page.
now i want to create next button on click of 2 page same. when i click on 2 page(ie 2nd button
then i want to create 3,4, button.. same way if i click on 6 than i wan to create next two button and prev button will seen which seen in above link.
my code is here:
Ext.define('Ext.bug.Newtoolbar', {
extend: 'Ext.toolbar.Toolbar',
alternateClassName: 'NewToolbar',
requires: ['Ext.toolbar.TextItem', 'Ext.button'],
mixins: {
bindable: 'Ext.util.Bindable'
},
autoDestroy: false,
displayInfo: false,
displayMsg: 'Displaying {0} - {1} of {2}',
emptyMsg: 'No data to display',
initComponent: function () {
var me = this,
pagingItems = me.addBtn(),
userItems = me.items || me.buttons || [];
if (me.prependButtons) {
me.items = userItems.concat(pagingItems);
} else {
me.items = pagingItems.concat(userItems);
}
//delete me.buttons;
if (me.displayInfo) {
me.items.push('->');
me.items.push({ xtype: 'tbtext', itemId: 'displayItem' });
}
me.callParent();
me.addEvents('change', 'beforechange');
me.on('beforerender', me.onLoad, me, { single: true });
me.bind(me.store || 'ext-empty-store', true);
},
// update here info...
updateInfo: function () {
var me = this,
displayItem = me.child('#displayItem'),
store = me.store,
pageData = me.getPageData(),
count, msg;
if (displayItem) {
count = store.getCount();
if (count === 0) {
msg = me.emptyMsg;
} else {
msg = Ext.String.format(
me.displayMsg,
pageData.fromRecord,
pageData.toRecord,
pageData.total
);
}
displayItem.setText(msg);
}
},
onLoad: function () {
var me = this,
pageData,
currPage,
pageCount,
afterText,
count,
isEmpty,
item;
count = me.store.getCount();
isEmpty = count === 0;
if (!isEmpty) {
pageData = me.getPageData();
currPage = pageData.currentPage;
pageCount = pageData.pageCount;
} else {
currPage = 0;
pageCount = 0;
}
Ext.suspendLayouts();
me.updateInfo();
me.updateLayout();
Ext.resumeLayouts(true);
if (me.rendered) {
me.fireEvent('change', me, pageData);
console.log('asd');
};
},
addBtn: function () {
var OnloadArray = [];
var me = this,
PageData,
currntPage,
PageCount;
PageData = me.getPageData();
currntPage = PageData.currentPage;
PageCount = PageData.pageCount;
for (var temp = 0; temp <= currntPage + 1; temp++) {
if (temp != 0) {
OnloadArray.push({
xtype: 'button',
itemId: temp,
scope: me,
text: temp,
enableToggle: true,
toggleGroup: me,
handler: me.btnHandler
});
}
};
OnloadArray.push({
xtype: 'tbtext',
scope: me,
text: '..........',
itemId: currntPage + 2
});
OnloadArray.push({
xtype: 'button',
itemId: PageCount - 1,
scope: me,
text: PageCount - 1,
enableToggle: true,
toggleGroup: me,
handler: me.btnHandler
});
OnloadArray.push({
xtype: 'button',
itemId: PageCount,
scope: me,
text: PageCount,
enableToggle: true,
toggleGroup: me,
handler: me.btnHandler
});
return OnloadArray;
},
getPageData: function () {
var store = this.store,
totalCount = store.getTotalCount();
return {
total: totalCount,
currentPage: store.currentPage,
pageCount: Math.ceil(totalCount / store.pageSize),
fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
};
}
});
please Help me Please
Thank You
Instead of coding it yourself, why not leverage off Ext JS's existing functionality?

Categories