Reload jstree window with new base node id - javascript

I have 2 JSTree windows, the first shows a directory tree, the second showing the files (not directories) within the selected directory.
var dirTree = $('#folders').jstree({
'core' : {
'data' : {
'url' : '/myUrl?action=tree',
'data' : function (node) {
return { 'id' : node.id };
}
}
}});
var fileTree = $('#files').jstree({
'core' : {
'data' : {
'url' : '/myUrl?action=files',
'data' : function (node) {
return { 'id' : node.id };
}
}
}});
// listen for event
$('#folders').on('select_node.jstree', function (e, data) {
fileTree.jstree("refresh");
}).jstree();
The above is the current state of my code, but I appreciate the jstree call in the select will need to change somehow.
When a directory is clicked on, I wish to have my list of files totally refreshed with the contents of the selected directory node. I believe I wish to ask how I set the base node when I refresh the file window, but if you think you know of a better way of doing this let me know.

If anyone has any other ideas, you are welcome to post an alternative answer.
My current solution is to set a baseId which is used as the id for the file window and then refreshed....
var baseId = '#';
var dirTree = $('#folders');
var fileTree = $('#files');
dirTree.jstree({
'core' : {
'data' : {
'url' : '/myUrl?action=tree',
'data' : function (node) {
return { 'id' : node.id };
}
}
}});
fileTree.jstree({
'core' : {
'data' : {
'url' : '/myUrl?action=files',
'data' : function (node) {
return { 'id' : baseId };
}
}
}});
// listen for event - could chain this with instantiation??
dirTree.on('select_node.jstree', function (e, data) {
baseId = data.selected[0];
fileTree.jstree("refresh");
}).jstree();

Related

Meteor: publish dynamically requested range of items

I have huge collection of over 5000+ records. I want to be able to view records 10 at a time. How can I dynamically publish the data that way?
I've tried this so far:
My server.js file :
Meteor.methods({
publishSongs : function (first, last) {
Meteor.publish('adminSongs', function() {
return Songs.find({}, {
skip : first,
limit : last,
sort : {
date : -1
}
});
});
}
});
My client.jsfile :
Template.admin.events({
'click #previous' : function() {
updateSession(-10);
publishSong();
},
'click #next' : function() {
updateSession(10);
publishSong();
}
});
Template.admin.onCreated(function() {
Session.setDefault('limit', {
first : 0,
last : 10
});
publishSong()
})
function publishSong() {
Meteor.call(
'publishSong',
Session.get('limit').first,
Session.get('limit').last
);
}
function updateSession(value) {
Session.set('limit', {
first: Session.get('limit').first + value,
last: Session.get('limit').last + value,
});
}
The server is printing this error message:
Ignoring duplicate publish named 'adminSongs'
It seems like I'm using publications wrong and could use some guidance.
It doesn't look like you're never updating your Session.get('limit'). You'll need to update then you press next/previous otherwise you're always going to get the same records. You'll also need to change the way you're doing publications:
Template.admin.events({
'click #previous' : function() {
updateSession(-10);
},
'click #next' : function() {
updateSession(10);
}
});
Template.admin.onCreated(function() {
Session.setDefault('limit', {
first : 0,
last : 10
});
Template.instance().autorun( function() {
Template.instance().subscribe('adminSongs', Session.get('limit').first, Session.get('limit').last);
});
});
function updateSession(value) {
Session.set('limit', {
first: Session.get('limit').first + value,
last: Session.get('limit').last + value,
});
}
I'm assuming based on your code that you already have a helper defined to return the available songs. The code above makes it so that you have one subscription, and that subscription will update any time your session variable changes.
Your server code will also need to be updated:
Meteor.publish('adminSongs', function(first, last) {
return Songs.find({}, {
skip : first,
limit : last,
sort : {
date : -1
}
});
});
Can be outside of a Meteor.method.

Polymer this and Cytoscape this

So I have a problem and it's most likely because I still don't get JavaScript... Cytoscape has their own 'this' and Polymer has their 'this'
<div id="labelFld">{{node.label}}</div>
<div id="measureFld">{{node.measure}}</div>
<div id="timesignatureFld">{{node.time_signature}}</div>
<div id="voiceFld">{{node.voice}}</div>
<div id="beatFld">{{node.beat}}</div>
<div id="meventFld">{{node.event}}</div>
var cy;
cytoscape({
ready : function () {
Polymer: ({
...
properties : {
node : {
type : Object,
notify : true,
readOnly : true
}
},
...
// Fires when the local DOM has been fully prepared
ready : function () {
var self_node = this.node; // <- 'this' via Polymer
try {
cy = cytoscape({
container : this.$.rhythmgraph,
ready : function (e) {}
});
} catch (err) {
console.log(err);
}
// Assign handler to Cytoscape click event for node elements
cy.on('click', 'node', {
"nodedata" : self_node // <- Seems to pass by value, not reference
}, function (e) {
self_node = this.data(); // <- 'this' via Cytoscape
console.log(self_node);
// e.data.nodedata = this.data();
});
},
But in order to update my <div>{{node.label}}</div> I have to be able to do this.node.label = "N42" // Polymer but I can't do it in the cy.on('click','node', ... ) because I need this.data() // Cytoscape inside there.
Scope is really killing me on this.
EDIT
In the end, I created an Observer to watch and update:
self_node = this.selectedNode;
var poly = this;
Object.observe(self_node, function(changes) {
changes.forEach(function(change) {
if(change.type == "update") {
poly.selectedNode = {
"id": change.object.id,
... }
};
poly.notifyPath('selectedNode.id', change.object.id);
}
});}.bind(poly));
I find this a common gotcha among JS dev beginners. You'll have to bind the function to its proper this reference.
cy.on('click', 'node', {
"nodedata" : rhynode
}, function (e) {
e.data.nodedata = this.data();
console.log(e.data.nodedata);
}.bind(this)); // here
With ES2015, arrow functions would bind automatically to the proper this:
cy.on('click', 'node', {
"nodedata" : rhynode
}, (e) => {
e.data.nodedata = this.data();
console.log(e.data.nodedata);
});

ReferenceError: $firebase is not defined

I am trying to unit test this service using jasmine:-
my unit test is :-
describe('initial configuration for the test user', function () {
beforeEach(function(){
var config = {
'Apache 404' : {
content : {
type : 'tip',
template : 'yesNo',
text : 'Are you searching for status code 404?',
yesText : 'Try our more accurate field search',
attachTo : '#inputBox right',
yesActions : {
0 : {
type : 'replaceSubstring',
target : '#inputBox',
value : 'apache.status:404',
match : '404'
}
}
},
conditions : {
0 : {
type : 'valueChange',
target : '#inputBox',
textMatch : '(^|([\\s]+))404(([\\s]+)|$)',
preventSubmit : true
},
1 : {
type : 'contentPropertyLessThan',
propertyName : 'timesShown',
compareVal : 3
}
}
}
};
var clientName = 'testClient';
var fireRef = new Firebase('https://luminous-inferno-1740.firebaseio.com/' + clientName);
var fireSync = $firebase(fireRef);
fireSync.$set({'config' : config});
log.message = 'Resetting user data';
$log.debug(log);
userData.init(function(done) {
done();
});
});
it('should have a valid config', function () {
expect(Object.keys(userData.getConfig()).length > 1);
});
});
I am receiving an error :-
ReferenceError: $firebase is not defined
at Object.
Can somebody help me providing working example of my code with some explanation?
I also had the problem. I solved my problem by adding $firebaseArray in the parameter of the controller
.controller('ChatsCtrl', ['$scope','$firebaseArray','$rootScope',......
One thing should be noted that firebase has been updated that $firebase is no longer supported. You can only use $firebaseArray or $firebaseObject for retrieving the data.

how to access function in Json

I am able to access the onclick properties function for the printButton property at the end of the block. Although I am unable to initiate the onclick functions under the exportButton property.I have the following code.
B.exporting = {
type : "image/png",
url : "http://export.highcharts.com/",
width : 800,
enableImages : false,
buttons : {
exportButton : {
symbol : "exportIcon",
x : -10,
symbolFill : "#A8BF77",
hoverSymbolFill : "#768F3E",
_titleKey : "exportButtonTitle",
menuItems : [{
textKey : "downloadPNG",
onclick : function() {
this.exportChart()
}
}, {
textKey : "downloadJPEG",
**onclick : function() {
this.exportChart({
type : "image/jpeg"
})**
}
}, {
textKey : "downloadPDF",
onclick : function() {
this.exportChart({
type : "application/pdf"
})
}
}, {
textKey : "downloadSVG",
onclick : function() {
this.exportChart({
type : "image/svg+xml"
})
}
}
}]
},
printButton : {
symbol : "printIcon",
x : -36,
symbolFill : "#B5C9DF",
hoverSymbolFill : "#779ABF",
_titleKey : "printButtonTitle",
onclick : function() {
this.print()
}
}
}
};
I am binding keyboard controls to the click events using the jquery plugin this is what I used to print. This Works!:
Mousetrap.bind('ctrl+s', function(e) { B.exporting.buttons.printButton.onclick(this.print());
});
This code is what I tried to access an individual onclick function under the exportButton property in the json above
Mousetrap.bind('*', function(e) {B.exporting.buttons.exportButton.menuItems[0].onclick;});
The result i get is the value but i want to run the function as the onclick property does.Does anyone know how to run a function under a json property?I Appreciate any help here thanks folks.
Mousetrap.bind('click', B.exporting.buttons.exportButton.menuItems[0].onclick);
Your ctrl-s binding also looks wrong, it should be:
Mousetrap.bind('ctrl+s', B.exporting.buttons.printButton.onclick);
The printButton.onclick function doesn't take an argument. Your binding calls this.print before calling the printButton.onclick function, and then the printButton.onclick function
does it again.

Backbone: Set the parent view's model (different from child model)

I have a Parent and Child view. The Child view extends the Parent events with:
initialize : function() {
// don't overwrite parent's events
this.events = _.extend( {}, ExerciseRowView.prototype.events, this.events);
},
However, the Parent expects a ParentModel and the Child expects a ChildModel, so when an event is passed to the Parent, the model is the ChildModel. How can I set the Parent model to be different from the Child model?
Thanks!
Here's the source, as requested.
ParentView aka ExerciseRowView:
var ExerciseRowView = Parse.View.extend( {
tagName : 'div',
className : 'exerciseWrapper',
template : _.template(exerciseElement),
events : {
'click .icon_delete' : 'confirmDelete',
'click .name' : 'showDetailsPopup'
},
confirmDelete : function() {
var that = this;
if(confirm("Are you sure you want to delete this exercise?")) {
this.destroy({
success: function(exercise) {
// log the action
Log.add(Log.ACTION_EXERCISE_DELETED, exercise.get("name"));
that.$el.fadeOut();
}
});
}
},
showDetailsPopup : function() {
(new ExerciseDetailsView({model: (this.model.constructor == Exercise ? this.model : this.model.get("exercise"))})).render();
},
// accept data as a parameter for workoutexercises
render : function(data) {
_.defaults(data, {
exercise: this.model,
Muscle : Muscle,
Equipment : Equipment,
Exercise : Exercise,
Break : Break,
HTMLHelper : HTMLHelper,
User : User
});
$(this.el).html(this.template(data));
return this;
}
});
ChildView aka WorkoutExerciseRowView:
var WorkoutExerciseRowView = ExerciseRowView.extend( {
events : {
"click .icon_randomize" : "changeToRandomExercise"
},
initialize : function() {
// don't overwrite parent's events
this.events = _.extend( {}, ExerciseRowView.prototype.events, this.events);
},
render: function() {
// override the template data with workout exercise template data
return ExerciseRowView.prototype.render.call(this, {
workoutExercise : this.model,
exercise : this.model.get("exercise"),
workoutSection : this.model.get("section"),
isEditable : true,
number : this.options.number,
WorkoutExercise : WorkoutExercise,
WorkoutSection : WorkoutSection
});
},
changeToRandomExercise : function(e) {
// pick a random alternative exercise
var newExerciseId;
do {
newExerciseId = _.keys(this.model.get("alternativeExercises"))[ Math.floor(Math.random() * _.keys(this.model.get("alternativeExercises")).length) ];
} while(newExerciseId == this.model.get("exercise").id);
// grab it
var that = this;
(new Parse.Query(Exercise)).get(newExerciseId, {
success: function(exercise) {
// update the workout exercise
that.model.set("exercise", exercise);
// render it
that.render();
}
});
}
});
Currently (as you can see), I test to see if this.model.constructor == Exercise inside ExerciseRowView. If it is not, I know that I have a WorkoutExercise, inside which is an Exercise, so I use this.model.get("exercise"):
showDetailsPopup : function() {
(new ExerciseDetailsView({model: (this.model.constructor == Exercise ? this.model : this.model.get("exercise"))})).render();
},
This doesn't seem like the cleanest possible solution, though.
what I could think of is that you define function for each view
ParentView
getExercise: function() {
return this.model;
}
ChildView
getExercise: function() {
return this.model.get('exercise');
}
And then change the function
showDetailsPopup: function() {
(new ExerciseDetailsView({model: this.getExercise()})).render();
}
How about that?

Categories

Resources