I have customized ace to handle Maven Java Projects. Most of the functionalities are working except autocomplete for Classes and Method.
Now I have created a trie to fill all classes.
var trie = new Trie();
trie.insert("java.util.HashTable");
trie.insert("java.util.HashMap");
trie.insert("java.util.HashSet");
When I call trie.autoComplete('java.util.H') then it shows all available classes. My ace editor code
var langTools = ace.require("ace/ext/language_tools");
langTools.addCompleter(javaCompletor);
var javaCompletor = {
getCompletions: function (editor, session, pos, prefix, callback) {
var currline = editor.getSelectionRange().start.row;
var content = editor.session.getLine(currline);
let arr = content.split(' ');
content = arr[arr.length-1];
callback(null, trie.autoComplete(content).map((a,b)=>{
return {value: a, score: 1, a: a, meta: '', type: 'snippet'}
}));
}
}
But my problem, it is not working quite well. Earlier text is not get replaced. And is it correct way of customizing autocomplete for Ace ?
Related
There is still something i don't get in accessing native Platform stuff with nativescript. Here is a simple snippet where i try to access a native gui element and add it to a page:
var PagesModule = require('ui/page');
var Application = require('application');
var StackLayout = require('ui/layouts/stack-layout').StackLayout;
exports.createPage = function createPage(args) {
var page = new PagesModule.Page;
page.actionBarHidden = true;
page.backgroundColor = '#F5F5F5';
page.backgroundSpanUnderStatusBar = false;
var textView = new android.widget.TextView(Application.android.currentContext);
var stackLayout = new StackLayout();
stackLayout.addChild(textView);
page.content = stackLayout;
return page;
}
I think i am missing something in the understanding of how nativescript interacts with the native platform.
The reason it is failing is because only "view" or "view" descendants can be assigned to "view" child or children.
You are creating a direct android component; but it isn't part of the NS framework, so the framework doesn't know what to do with it. When you create a visual component you descend your component from a view (or another view descendant). The NS version of the code should be:
var PagesModule = require('ui/page');
var Application = require('application');
var StackLayout = require('ui/layouts/stack-layout').StackLayout;
vat TextView = require('ui/text-view').TextView;
exports.createPage = function createPage(args) {
var page = new PagesModule.Page;
page.actionBarHidden = true;
page.backgroundColor = '#F5F5F5';
page.backgroundSpanUnderStatusBar = false;
var textView = new TextView();
var stackLayout = new StackLayout();
stackLayout.addChild(textView);
page.content = stackLayout;
return page;
}
If you are actually wanting to create your own component I would recommend you look at the UI/Switch it is probably the simplest example; but in a nutshell you need to subclass the view, on Android use the function _createUI to actually create the native component, and so in simplest terms it would be:
var View = require('ui/core/view').View;
function MyTextView() {
View.apply(this, arguments);
}
__extends(MyTextView, View);
Object.defineProperty(MyTextView.prototype, "android", {
get: function () {
return this._android;
},
enumerable: true,
configurable: true
});
MyTextView.prototype._createUI = function () {
this._android = new android.widget.TextView(Application.android.currentContext);
};
Then you can use new MyTextView() instead of the built in new TextView() function in the first code sample.
Please note with this component, because we haven't defined any additional helper function, to set and get the text you would have to do things like
var x = page.GetViewById('myTextId').android.setText("Some Value");
and to access the native underlying control and its android properties.
Please note I have a whole blog article on some of this at http://fluentreports.com/blog/?p=167 (And many other articles on the site about NS)
i'm trying to build angular2 component which draws chart (using jquery plot)
import {Component, ElementRef, Input, OnChanges} from 'angular2/core';
#Component({
selector: 'flot',
template: `<div>loading</div>`
})
export class FlotCmp implements OnChanges{
private width = '100%';
private height = 220;
static chosenInitialized = false;
#Input() private options: any;
#Input() private dataset:any;
#Input() private width:string;
#Input() private height:string;
constructor(public el: ElementRef) {}
ngOnChanges() {
if(!FlotCmp.chosenInitialized) {
let plotArea = $(this.el.nativeElement).find('div').empty();
plotArea.css({
width: this.width,
height: this.height
});
$.plot( plotArea, this.dataset, this.options);
FlotCmp.chosenInitialized = true;
}
}
}
Component getting chart "data" property as input parameter:
<flot [options]="splineOptions" [dataset]="dataset" height="250px" width="100%"></flot>
So far i managed to make it work as long as "dataset" is static variable.
this.dataset = [{label: "line1",color:"blue",data:[[1, 130], [3, 80], [4, 160], [5, 159], [12, 350]]}];
My problem is to make it work when data came as a promise:
export class App implements OnInit {
private dataset:any;
public entries;
getEntries() {
this._flotService.getFlotEntries().then(
entries => this.dataset[0].data = entries,
error => this.errorMessage = <any>error);
}
ngOnInit() {
this.getEntries()
}
constructor(private _flotService:FlotService) {
this.name = 'Angular2'
this.splineOptions = {
series: {
lines: { show: true },
points: {
radius: 3,
show: true
}
}
};
this.dataset = [{label: "line1",color:"blue",data:null]}];
}
}
For some reason data change cannot project to "flot" component
here is link to plunk
Please help
The problem is
entries => this.dataset[0].data = entries,
because only the inner state of the bound value is changed and Angular2 change detection doesn't observe the content only the value or reference itself.
A workaround would be to create a new array with the same content
this._flotService.getFlotEntries().then(
entries => {
this.dataset[0].data = entries;
this.dataset = this.dataset.slice();
},
In your case an additional event could work that notifies the child component that updates have happended.
Besides Günter's answer, another option is to implement your own change detection inside ngDoCheck() which will be called when your data comes back from the server:
ngDoCheck() {
if(this.dataset[0].data !== null && !this.dataPlotted) {
console.log('plotting data');
let plotArea = $(this.el.nativeElement).find('div').empty();
$.plot( plotArea, this.dataset, this.options);
this.dataPlotted = true;
}
}
I feel this is a cleaner approach, since we don't have to write code a specific way just to satisfy/trigger Angular change detection. But alas, it is less efficient. (I hate it when that happens!)
Also, the code you have in ngOnChanges() can be moved to ngOnInit().
Plunker
As Günter already mentioned, ngOnChanges() isn't called because the dataset array reference doesn't change when you fill in your data. So Angular doesn't think any input properties changed, so ngOnChanges() isn't called. ngDoCheck() is always called every change detection cycle, whether or not there are any input property changes.
Yet another option is to use #ViewChild(FlotCmp) in the parent component, which will get a reference to FlotCmp. The parent could then use that reference to call some method, say drawPlot(), on FlotCmp to draw/update the plot when the data arrives.
drawPlot(dataset) {
console.log('plotting data', dataset);
let plotArea = $(this.el.nativeElement).find('div').empty();
$.plot( plotArea, dataset, this.options);
this.dataset = dataset;
}
Plunker
This is more efficient than ngDoCheck(), and it doesn't have the issue I described above with the ngOnChanges() approach.
However, if I were to use this approach, I would rework the code somewhat, since I don't like how dataset is currently an input property, but then drawPlot() gets the data passed in via a function argument.
i've a little issue for calling new icon with leaflet.
this is my code and i'm using the ajax lib leaflet-ajax.
var map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var Icon1 = L.icon({
iconUrl: '/img/pin.svg',
iconSize: [38, 40]
});
var Icon2 = L.icon({
iconUrl: '/img/pin2.svg',
iconSize: [38, 40]
});
var Icon3 = L.icon({
iconUrl: '/img/pin3.svg',
iconSize: [38, 40]
});
function popUp(feature, layer) {layer.bindPopup('<p><b>' + feature.properties.name + '</b></p>' + '<p>' + feature.properties.description + '</p>');}
function popUp2(feature, layer) {layer.bindPopup('<p><b>' + feature.properties.name + '</b></p>' + '<p>' + feature.properties.special + '</p>');}
and where i think i have my issue with the call method for the icon
// call json
var geojsonLayer1 = new L.GeoJSON.AJAX("/json/jsonlayer1.json", {onEachFeature:popUp}, {icon:Icon1});
var geojsonLayer2 = new L.GeoJSON.AJAX("/json/jsonlayer2.json", {onEachFeature:popUp}, {icon:Icon2});
var geojsonLayer3 = new L.GeoJSON.AJAX("/json/jsonlayer3.json", {onEachFeature:popUp2}, {icon:Icon3});
// create group layer
var group1 = L.layerGroup([geojsonLayer1]);
var group2 = L.layerGroup([geojsonLayer2]);
var group3 = L.layerGroup([geojsonLayer3]);
// call group layer on dialog box
var checkboxesJson = {
"layer1": group1,
"layer2": group2,
"layer3": group3
};
L.control.layers(null,checkboxesJson).addTo(map);
Thank you for your help !
If my understanding is correct, you are trying to create a customized GeoJSON layer group through using leaflet-ajax plugin. But you do not know how to specify the icon that should be applied on markers for points of your GeoJSON data?
It looks like this plugin will simply use all standard L.GeoJSON options that are specified in the second argument of the constructor / factory, as you did for your onEachFeature option. Note that you can have many options in one single object.
However, you should use option pointToLayer instead of just icon, which is an option for a Marker. The function that you pass to pointToLayer should return an L.Marker, where indeed you would use the icon option.
For example you could do:
var geojsonLayer1 = L.geoJson.ajax(
"/json/jsonlayer1.json",
{
onEachFeature: popUp,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, { icon: Icon1 })
}
});
Note that it is usually recommended to instantiate one icon per marker, even though it should work in your simple case.
By the way, note that L.geoJson (and with ajax plugin, L.geoJson.ajax) return an extended type of L.LayerGroup, so you do not have to import them into a new Layer Group to be able to use them in the Layers Control.
Therefore you could directly do:
// call group layer on dialog box
var checkboxesJson = {
"layer1": geojsonLayer1,
"layer2": geojsonLayer2,
"layer3": geojsonLayer3
};
L.control.layers(null,checkboxesJson).addTo(map);
I'll start off by stating that I don't know if this is possible at all, but I'm reading over the Kendo UI documentation and trying to figure out how to at least try it, but I'm running into a lot of difficulties with making a custom binding. This is a followup to another question I am still working on, which is posted here. If this is not an appropriate question, please kindly let me know, and I will close it or rephrase it. I'm just really lost and confused at this point.
As I understand it, based on what I've been told and tried, Kendo cannot bind to an Associative Array not because the data isn't good, but because it is an array of objects, each as a separate individual entity - under normal circumstances, an array would be a bit different and contain a length property, as well as some other functions in the array prototype that make iteration through it possible.
So I was trying to conjecture how to get around this. I succeeded in getting what I think was a workaround to function. I preface that with "think" because I'm still too inexperienced with Javascript to truly know the ramifications of doing it this way (performance, stability, etc)
Here is what I did;
kendo template
<script type="text/x-kendo-template" id="display-items-many">
# for(var key in data) { #
# if (data.hasOwnProperty(key) && data[key].hasOwnProperty("Id")) { #
<tr>
<td>
<strong>#= data[key].Id #</strong>
</td>
<td class="text-right">
<code>#= data[key].Total #</code>
</td>
</tr>
# } #
# } #
</script>
html
<table class="table borderless table-hover table-condensed" data-bind="source: Associative data-template="display-items-many">
</table>
Now to me, immediately off hand, this gave me the illusion of functioning. So I got to thinking a bit more on how to fix this ...
I want to create a new binding called repeat. The goal of this binding is as follows;
repeat the template for each instance of an object within the given root object that meets a given criteria
In my head, this would function like this;
<div data-template="repeater-sample" data-bind="repeat: Associative"></div>
<script type="text/x-kendo-template" id="repeater-sample">
<div> ${ data.Id }</div>
</script>
And the criteria would be a property simply called _associationKey. So the following would, in theory, work.
$.ajax({
// get data from server and such.
}).done(function(results){
// simple reference to the 'associative array' for easier to read code
var associative = results.AssociativeArray;
// this is a trait that everything in the 'associative array' should have to match
// this is purely, purely an example. Obviously you would use a more robust property
var match = "Id";
// go through the results and wire up the associative array objects
for(var key in associative ) {
if(associative.hasOwnProperty(key) && associative[key].hasOwnProperty(match)) {
associative[key]._associationKey = 10; // obviously an example value
}
}
// a watered down example implementation, obviously a real use would be more verbose
viewModel = kendo.observable({
// property = results.property
// property = results.property
associativeArray = associative
});
kendo.bind('body', viewModel);
});
So far this actually seems to work pretty well, but I have to hard code the logic in the template using inline scripting. That's kind of what I want to avoid.
Problem
The big issue is that I'm vastly confused on telerik's documentation for custom bindings (available here). I do have their examples to draw from, yes - but it's a bit confusing to me how it interacts with the object. I'll try to explain, but I'm so lost that it may be difficult.
This is what telerik gives for an example custom binding, and I've pruned it a bit for space concerns;
<script>
kendo.data.binders.repeater = kendo.data.Binder.extend({
init: function(element, bindings, options) {
//call the base constructor
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var that = this;
// how do we interact with the data that was bound?
}
});
</script>
So essentially that's where I am lost. I'm having a big disconnect figuring out how to interact with the actual "associative array" that is bound using data-bind="repeat: associativeArray"
So ..
I need to interact with the bound data (the entire 'associative array')
I need to be able to tell it to render the target template for each instance that matches
Further Updates
I have been digging through the kendo source code, and this is what I have so far - by taking the source binding as an example... but I'm still not getting the right results. Unfortunately this poses a few problems;
some of the functions are internal to kendo, I'm not sure how to get access to them without re-writing them. While I have the source and can do that, I'd prefer to make version agnostic code so that it can "plug in" to newer releases
I'm totally lost about what a lot of this does. I basically made a copy of the source binding and replaced it with my own syntax where possible, since the concept is fundamentally the same. I cannot figure out where to do the test for qualification to be rendered, if that makes sense.
I'm having a big logic disconnect here - there should ideally be some place where I can basically say ... If the current item that kendo is attempting to render in a template matches a criteria, render it. If not, pass it over and then another place where I tell it to iterate over every object in the 'associative array' so as to get to the point where I test it.
I feel just forcing a for loop in here will actually make this fire too many times, and I am getting pretty lost. Any help is greatly appreciated.
kendo.data.binders.repeat = kendo.data.Binder.extend({
init: function(element, bindings, options) {
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var source = this.bindings.repeat.get();
if (source instanceof kendo.data.DataSource && options.autoBind !== false) {
source.fetch();
}
},
refresh: function(e) {
var that = this,
source = that.bindings.repeat.get();
if (source instanceof kendo.data.ObservableArray|| source instanceof kendo.data.DataSource) {
e = e || {};
if (e.action == "add") {
that.add(e.index, e.items);
} else if (e.action == "remove") {
that.remove(e.index, e.items);
} else if (e.action != "itemchange") {
that.render();
}
} else {
that.render();
}
},
container: function() {
var element = this.element;
if (element.nodeName.toLowerCase() == "table") {
if (!element.tBodies[0]) {
element.appendChild(document.createElement("tbody"));
}
element = element.tBodies[0];
}
return element;
},
template: function() {
var options = this.options,
template = options.template,
nodeName = this.container().nodeName.toLowerCase();
if (!template) {
if (nodeName == "select") {
if (options.valueField || options.textField) {
template = kendo.format('<option value="#:{0}#">#:{1}#</option>',
options.valueField || options.textField, options.textField || options.valueField);
} else {
template = "<option>#:data#</option>";
}
} else if (nodeName == "tbody") {
template = "<tr><td>#:data#</td></tr>";
} else if (nodeName == "ul" || nodeName == "ol") {
template = "<li>#:data#</li>";
} else {
template = "#:data#";
}
template = kendo.template(template);
}
return template;
},
add: function(index, items) {
var element = this.container(),
parents,
idx,
length,
child,
clone = element.cloneNode(false),
reference = element.children[index];
$(clone).html(kendo.render(this.template(), items));
if (clone.children.length) {
parents = this.bindings.repeat._parents();
for (idx = 0, length = items.length; idx < length; idx++) {
child = clone.children[0];
element.insertBefore(child, reference || null);
bindElement(child, items[idx], this.options.roles, [items[idx]].concat(parents));
}
}
},
remove: function(index, items) {
var idx, element = this.container();
for (idx = 0; idx < items.length; idx++) {
var child = element.children[index];
unbindElementTree(child);
element.removeChild(child);
}
},
render: function() {
var source = this.bindings.repeat.get(),
parents,
idx,
length,
element = this.container(),
template = this.template();
if (source instanceof kendo.data.DataSource) {
source = source.view();
}
if (!(source instanceof kendo.data.ObservableArray) && toString.call(source) !== "[object Array]") {
source = [source];
}
if (this.bindings.template) {
unbindElementChildren(element);
$(element).html(this.bindings.template.render(source));
if (element.children.length) {
parents = this.bindings.repeat._parents();
for (idx = 0, length = source.length; idx < length; idx++) {
bindElement(element.children[idx], source[idx], this.options.roles, [source[idx]].concat(parents));
}
}
}
else {
$(element).html(kendo.render(template, source));
}
}
});
I would propose as a simpler solution transform transmitted associative array in an array. This is pretty simple and (for most cases) can solve your problem.
Lets say that you get the following associative array received from the server:
{
"One" : { Name: "One", Id: "id/one" },
"Two" : { Name: "Two", Id: "id/two" },
"Three" : { Name: "Three", Id: "id/three" }
}
That is store in a variable called input. Transform it from associative to no associative is as easy as:
var output = [];
$.each(input, function(idx, elem) {
elem.index = idx;
output.push(elem);
});
Now, you have in output an equivalent array where I saved the index field into a field called index for each element of the associative array.
Now you can use out-of-the-box code for displaying the data received from the server.
See it in action here : http://jsfiddle.net/OnaBai/AGfWc/
You can even use KendoUI DataSource for retrieving and transforming the data by using DataSource.schema.parse method as:
var dataSource = new kendo.data.DataSource({
transport: {
read: ...
},
schema : {
parse: function (response) {
var output = [];
$.each(response, function(idx, elem) {
elem.index = idx;
output.push(elem);
});
return output;
}
}
});
and your model would be:
var viewModel = new kendo.data.ObservableObject({
Id: "test/id",
Associative: dataSource
});
You can see it in action here: http://jsfiddle.net/OnaBai/AGfWc/1/
I am trying to link to a specific tab in Magento Enterprise. It seems that all of the answers I've found don't apply well to their method. I just need a link to the page to also pull up a specific tab. This is the code they use:
Enterprise.Tabs = Class.create();
Object.extend(Enterprise.Tabs.prototype, {
initialize: function (container) {
this.container = $(container);
this.container.addClassName('tab-list');
this.tabs = this.container.select('dt.tab');
this.activeTab = this.tabs.first();
this.tabs.first().addClassName('first');
this.tabs.last().addClassName('last');
this.onTabClick = this.handleTabClick.bindAsEventListener(this);
for (var i = 0, l = this.tabs.length; i < l; i ++) {
this.tabs[i].observe('click', this.onTabClick);
}
this.select();
},
handleTabClick: function (evt) {
this.activeTab = Event.findElement(evt, 'dt');
this.select();
},
select: function () {
for (var i = 0, l = this.tabs.length; i < l; i ++) {
if (this.tabs[i] == this.activeTab) {
this.tabs[i].addClassName('active');
this.tabs[i].style.zIndex = this.tabs.length + 2;
/*this.tabs[i].next('dd').show();*/
new Effect.Appear (this.tabs[i].next('dd'), { duration:0.5 });
this.tabs[i].parentNode.style.height=this.tabs[i].next('dd').getHeight() + 15 + 'px';
} else {
this.tabs[i].removeClassName('active');
this.tabs[i].style.zIndex = this.tabs.length + 1 - i;
this.tabs[i].next('dd').hide();
}
}
}
});
Anyone have an idea?
I would consider modifying how the class starts up.
initialize: function (container) {
this.container = $(container);
this.container.addClassName('tab-list');
this.tabs = this.container.select('dt.tab');
// change starts here //
var hashTab = $(window.location.hash.slice(1));
this.activeTab = ( this.tabs.include(hashTab) ? hashTab : this.tabs.first());
// change ends here //
this.tabs.first().addClassName('first');
this.tabs.last().addClassName('last');
this.onTabClick = this.handleTabClick.bindAsEventListener(this);
for (var i = 0, l = this.tabs.length; i < l; i ++) {
this.tabs[i].observe('click', this.onTabClick);
}
this.select();
}
Here, I have only changed how the initial tab is chosen. It checks for an URL fragment which is commonly known as a hash, if that identifies one of the tabs it is preselected. As a bonus the browser will also scroll to that element if possible.
Then you only need to append the tab's ID to the URL. For example you might generate the URL by;
$productUrl = Mage::getUrl('catalog/product/view', array(
'id' => $productId,
'_fragment' => 'tab_id',
));
If you've recently migrated from an earlier Magento release, e.g. from Enterprise 1.11 to Enterprise 1.12, make sure the javascript in /template/catalog/product/view.phtml
right after the foreach that generates the tabs gets updated to the 1.12 version:
<script type="text/javascript">
var collateralTabs = new Enterprise.Tabs('collateral-tabs');
Event.observe(window, 'load', function() {
collateralTabs.select();
});
</script>
surfimp's VERY helpful suggestions did not produce the desired opening of the closed tab otherwise. Once this updated javascript was added, clicking on a link to read Review or Add Your Review on the product page, jumped to the Reviews tab, even if the tab had been hidden.
Similar to Zifius' answer, you can modify the initialize function to just take another argument which will be the active tab.
Event.observe(window, 'load', function() {
new Enterprise.Tabs('collateral-tabs', $('tab_review'));
});
and then in the scripts.js (or wherever this class may exist for you)
initialize: function (container, el) {
...
this.activeTab = el;
...
}
Use whatever logic in the template you like to set 'el' to the desired value.
The reason I did it this way is because when I used Zifius' method, the desired tab would be the active tab, but the default tab's content was still displayed.
Had the same task yesterday and as I don't know about prototype much I solved it by adding another method:
selectTab: function (element) {
this.activeTab = element;
this.select();
},
Usage:
var Tabs = new Enterprise.Tabs('collateral-tabs');
Tabs.selectTab($('tabId'));
Would like to know if it's a correct approach