Related
I have written code for a terminal UI application using blessed package in NodeJS which contains 2 forms, say form1 and form2 with some widgets like list and checkboxes in each form. So how can I navigate between the forms with keyboard?
var blessed = require('blessed');
// Create a screen object.
var screen = blessed.screen({
smartCSR: true
});
screen.title = 'my window title';
var parentform = blessed.form({
parent: screen,
keys: true,
left: 0,
top: 2,
width: 80,
height: 50,
// bg: 'green',
content: '',
border:{
type:'line'
},
style:{
border:{
fg:'green',
bg:'green'
}
}
});
var list = blessed.List({
top:2,
left:'center',
parent:parentform,
height:8,
width:20,
mouse:true,
keys:true,
items:["abc","xyz","123","456"],
border:{
type:'line'
},
style:{
selected:{
bg:'blue',
fg:'white'
},
item:{
bg:'white',
fg:'blue'
},
// focus:{
// bg:'red'
// }
}
});
var parentform_cb1 = blessed.Checkbox({
parent: parentform,
top:12,
left:10,
content:"cb1",
height:1,
width:12,
// bg:'white',
mouse:true
});
var parentform_cb2 = blessed.Checkbox({
parent: parentform,
top:14,
left:10,
content:"cb2",
height:1,
width:12,
// bg:'white',
mouse:true
});
var parentform_cb3 = blessed.Checkbox({
parent: parentform,
top:16,
left:10,
content:"cb3",
height:1,
width:12,
// bg:'white',
mouse:true
});
var parentform_cb4 = blessed.Checkbox({
parent: parentform,
top:18,
left:10,
content:"cb4",
height:1,
width:12,
// bg:'white',
mouse:true
});
var parentform_cb5 = blessed.Checkbox({
parent: parentform,
top:20,
left:10,
content:"cb5",
height:1,
width:12,
// bg:'white',
mouse:true
});
var form2 = blessed.form({
parent: screen,
keys: true,
left: 90,
top: 2,
width: 80,
height: 50,
content: '',
mouse:true,
scrollable:true,
scrollbar: {
style: {
bg: 'blue'
},
},
border:{
type:'line'
},
style:{
border:{
fg:'green',
bg:'green'
}
}
});
var form2_cb1 = blessed.Checkbox({
parent: form2,
top:4,
left:4,
content:"form2 cb2",
height:1,
width:18,
mouse:true
});
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
list.focus();
screen.render();
Currently I am able to do it with a mouse, but how can i do it with keyboard?
To navigate between the forms you can simply, attach a key event to the last checkbox item of form1 and the checkbox item of form2.
parentform_cb5.key(["tab"], function (ch, key) {
// focuses on form 2 when you press tab
form2.focusNext();
});
form2_cb1.key(["tab"], function (ch, key) {
// focuses back on the screen when you press tab
screen.focusNext();
});
I am trying to show a popup as explained and i am not able to add one. Here is the code HTML followed by JS.
I have added a button and on click of the button i am trying to show popup. I was able to show a popup without the webix.ready() function, but when i try to add that my code breaks. Any help regarding this would be of real help.
HTML CODE:
<body>
<div class="loader-holder" id="loader-holder">
<div class="loader-container">
<p>Loading......</p>
</div>
</div>
</body>
JS CODE:
var form = {
view:"form",
borderless:true,
elements: [
{ view:"text", label:'Login', name:"login" },
{ view:"text", label:'Email', name:"email" },
{ view:"button", value: "Submit", click:function(){
if (this.getParentView().validate()){ //validate form
webix.message("All is correct");
this.getTopParentView().hide(); //hide window
}
else
webix.message({ type:"error", text:"Form data is invalid" });
}}
],
rules:{
"email":webix.rules.isEmail,
"login":webix.rules.isNotEmpty
},
elementsConfig:{
labelPosition:"top",
}
};
function showForm(winId, node){
console.log(node);
$$(winId).getBody().clear();
$$(winId).show(node);
$$(winId).getBody().focus();
}
var popup = {view:"popup",id:"win1",width:300,head:false,body:webix.copy(form)};
function Start(){
var tbl = {
}
var cfg = {
container:"listC",
width:1500,
height:600,
rows:[
{
height: 35,
view:"toolbar",
elements:[
{view:"text", id:"grouplist_input",label:"Filter",css:"fltr", labelWidth:170}
]
},
{ view:"button",value: 'Click to show a popup with a form',click:function(){ showForm("win1", popup)}},
]
}
/////////////////////////////////
var bodycontent =
{
id:"tb", autoheight:true,autowidth:true,
view:"tabview",
cells:[
{
header:"LIVE",
body: tbl
},
{
header:"REMOTE WATCH",
body: { id:"remote_watch", template:"some_text"}
},
{
header:"CONFIG",
body:cfg//{ id:"config", template:"CONFIG is In developement........"}
} ]
}
var label = { view:"label", label:'some_text ',height:25, align:"left",css:"my_style"}
webix.ready(function ()
{
var el = document.getElementById('loader-holder');
el.parentNode.removeChild(el);
webix.i18n.parseFormatDate = webix.Date.strToDate("%m/%d/%Y");
webix.ui(
{
view: "layout",
id: "dashboard",
rows:
[
label,
bodycontent
]
})
});
}
You can use popup functionality from
Bootstrap. It has good documentation.
You need to initialize popup before using it. You can do it wherever you want to (ex. webix.ready(), "showForm" function)
var form = {
view:"form",
borderless:true,
elements: [
{ view:"text", label:'Login', name:"login" },
{ view:"text", label:'Email', name:"email" },
{ view:"button", value: "Submit", click:function(){
if (this.getParentView().validate()){ //validate form
webix.message("All is correct");
this.getTopParentView().hide(); //hide window
}
else
webix.message({ type:"error", text:"Form data is invalid" });
}}
],
rules:{
"email":webix.rules.isEmail,
"login":webix.rules.isNotEmpty
},
elementsConfig:{
labelPosition:"top",
}
};
function showForm(winId, node){
webix.ui(popup);
$$(winId).getBody().clear();
$$(winId).show(node);
$$(winId).getBody().focus();
}
var popup = {view:"popup",id:"win1",width:300,head:false,body:webix.copy(form)};
function Start(){
var tbl = {
}
var cfg = {
container:"listC",
width:1500,
height:600,
rows:[
{
height: 35,
view:"toolbar",
elements:[
{view:"text", id:"grouplist_input",label:"Filter",css:"fltr", labelWidth:170}
]
},
{ view:"button",value: 'Click to show a popup with a form',click:function(){ showForm("win1", this.$view)}},
]
}
/////////////////////////////////
var bodycontent =
{
id:"tb", autoheight:true,autowidth:true,
view:"tabview",
cells:[
{
header:"LIVE",
body: tbl
},
{
header:"REMOTE WATCH",
body: { id:"remote_watch", template:"some_text"}
},
{
header:"CONFIG",
body:cfg//{ id:"config", template:"CONFIG is In developement........"}
} ]
}
var label = { view:"label", label:'some_text ',height:25, align:"left",css:"my_style"}
webix.ready(function ()
{
var el = document.getElementById('loader-holder');
el.parentNode.removeChild(el);
webix.i18n.parseFormatDate = webix.Date.strToDate("%m/%d/%Y");
webix.ui(
{
view: "layout",
id: "dashboard",
rows:
[
label,
bodycontent
]
})
});
}
Start();
https://webix.com/snippet/459c4dd6
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?
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
I have a fine working jquery multicolumn autocomplete. Now i have to add a column which should be hidden. Basically its a ID of the values. So when the user selects the value i could able to get the ID of the selected row.
//Code:
<script type="text/javascript">
var autocompleteSource;
var colValues = [];
var columns = [{ name: 'Workflow Name', width: '200px' }, { name: 'Workflow Category', width: '150px' }, { name: 'Status', width: '100px' }, { name: 'Workflow Owner', width: '150px' }];
$.ajax({
url: "/Home/LoadWorkflowDropdown",
datatype: 'json',
mtype: 'GET',
success: OnComplete,
error: OnFail
});
function OnComplete(result) {
autocompleteSource = $.parseJSON(result)
$.each(autocompleteSource, function () {
colValues.push([this.WorkflowName, this.WorkflowCategory, this.StatusName, this.UserName]);
});
$.widget('custom.mcautocomplete', $.ui.autocomplete, {
_renderMenu: function (ul, items) {
var self = this,
thead;
if (this.options.showHeader) {
table = $('<div class="ui-widget-header" style="width:100%"></div>');
$.each(this.options.columns, function (index, item) {
table.append('<span style="padding:0 4px;float:left;width:' + item.width + ';">' + item.name + '</span>');
});
table.append('<div style="clear: both;"></div>');
ul.append(table);
}
$.each(items, function (index, item) {
self._renderItem(ul, item);
});
},
_renderItem: function (ul, item) {
var t = '',
result = '';
$.each(this.options.columns, function (index, column) {
t += '<span style="padding:0 4px;float:left;width:' + column.width + ';">' + item[column.valueField ? column.valueField : index] + '</span>'
});
result = $('<li></li>').data('item.autocomplete', item).append('<a class="mcacAnchor">' + t + '<div style="clear: both;"></div></a>').appendTo(ul);
return result;
}
});
$("#search").mcautocomplete({
showHeader: true,
columns: columns,
source: colValues,
select: function (event, ui) {
this.value = (ui.item ? ui.item[0] : '');
return false;
}
});
}
</script>
Working Fiddle here
Here i have modified js code to add unique id to each record and to get that value when user selects a particular option from the auto-suggest list. Fiddle
HTML: Create a hidden field to store the id of selected option
<input type="hidden" name="selectedId" id="selectedId" />
JS: Added ids in the array and retrieved those ids in select function by index value.
var columns = [{
name: 'Color',
width: '100px'},
{
name: 'Hex',
width: '70px'}],
colors = [['Red', '#f00', '1'], ['Green', '#0f0', '2'], ['Blue', '#00f', '3']];
$("#search").mcautocomplete({
showHeader: true,
columns: columns,
source: colors,
select: function(event, ui) {
$('#selectedId').val(ui.item[2]);
this.value = (ui.item ? ui.item[0] : '');
return false;
}
});