Commit b25b31e4 by Torkel Ödegaard

Merge branch 'master' into develop

parents e51d4034 88d27fe6
...@@ -30,7 +30,7 @@ a standalone frontend only web application. Grafana 2.0 comes with a backend. ...@@ -30,7 +30,7 @@ a standalone frontend only web application. Grafana 2.0 comes with a backend.
- Click and drag to zoom - Click and drag to zoom
- Multiple Y-axis, logarithmic scales - Multiple Y-axis, logarithmic scales
- Bars, Lines, Points - Bars, Lines, Points
- Smart Y-axis formating - Smart Y-axis formatting
- Series toggles & color selector - Series toggles & color selector
- Legend values, and formatting options - Legend values, and formatting options
- Grid thresholds, axis labels - Grid thresholds, axis labels
......
...@@ -225,7 +225,7 @@ level = Info ...@@ -225,7 +225,7 @@ level = Info
[log.console] [log.console]
level = level =
# Set formatting to "false" to disable color formatting of console logs # Set formatting to "false" to disable color formatting of console logs
formatting = true formatting = false
# For "file" mode only # For "file" mode only
[log.file] [log.file]
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Grafana docker image # Grafana docker image
This container currently only contains the in development alpha of Grafana 2.0 (ie non production use). The This container currently only contains the in development alpha of Grafana 2.0 (ie non production use). The
`#develop` tag is constantly updated as we make progress torwards a beta release. `#develop` tag is constantly updated as we make progress towards a beta release.
## Running your Grafana image ## Running your Grafana image
...@@ -17,7 +17,7 @@ Try it out, default admin user is admin/admin. ...@@ -17,7 +17,7 @@ Try it out, default admin user is admin/admin.
## Configuring your Grafana container ## Configuring your Grafana container
All options defined in conf/grafana.ini can be overriden using environment variables, for example: All options defined in conf/grafana.ini can be overridden using environment variables, for example:
``` ```
......
...@@ -54,6 +54,25 @@ Example content: ...@@ -54,6 +54,25 @@ Example content:
You need to specify a namespace, metric, at least one stat, and at least one dimension. You need to specify a namespace, metric, at least one stat, and at least one dimension.
## Templated queries
CloudWatch Datasource Plugin provides the following functions in `Variables values query` field in Templating Editor to query `region`, `namespaces`, `metric names` and `dimension keys/values` on the CloudWatch.
Name | Description
------- | --------
`regions()` | Returns a list of regions AWS provides their service.
`namespaces()` | Returns a list of namespaces CloudWatch support.
`metrics(namespace)` | Returns a list of metrics in the namespace.
`dimension_keys(namespace)` | Returns a list of dimension keys in the namespace.
`dimension_values(region, namespace, metric)` | Returns a list of dimension values matching the specified `region`, `namespace` and `metric`.
For details about the metrics CloudWatch provides, please refer to the [CloudWatch documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html).
If you want to filter dimension values by other dimension key/value pair, you can specify optional parameter like this.
```sql
dimension_values(region, namespace, metric, dim_key1=dim_val1,dim_key2=dim_val2,...)
```
![](/img/v2/cloudwatch_templating.png)
## Cost ## Cost
......
...@@ -30,18 +30,23 @@ Open a graph in edit mode by click the title. ...@@ -30,18 +30,23 @@ Open a graph in edit mode by click the title.
![](/img/v2/opentsdb_query_editor.png) ![](/img/v2/opentsdb_query_editor.png)
### Auto complete suggestions ### Auto complete suggestions
You should get auto complete suggestions for tags and tag values. If you do not you need to enable `tsd.core.meta.enable_realtime_ts` in As soon as you start typing metric names, tag names and tag values , you should see highlighted auto complete suggestions for them.
the OpenTSDB server settings.
> Note: This is required for the OpenTSDB `lookup` api to work. > Note: This is required for the OpenTSDB `suggest` api to work.
## Templating queries ## Templating queries
Grafana's OpenTSDB data source now supports template variable values queries. This means you can create template variables that fetch the values from OpenTSDB (for example metric names, tag names, or tag values). The query editor is also enhanced to limiting tags by metric. Grafana's OpenTSDB data source now supports template variable values queries. This means you can create template variables that fetch the values from OpenTSDB (for example metric names, tag names, or tag values). The query editor is also enhanced to limiting tags by metric.
When using OpenTSDB with a template variable of `query` type you can use following syntax for lookup. When using OpenTSDB with a template variable of `query` type you can use following syntax for lookup.
metrics() // returns metric names metrics(prefix) // returns metric names with specific prefix (can be empty)
tag_names(cpu) // return tag names (i.e. keys) for a specific cpu metric tag_names(cpu) // return tag names (i.e. keys) for a specific cpu metric
tag_values(cpu, hostname) // return tag values for metric cpu and tag key hostname tag_values(cpu, hostname) // return tag values for metric cpu and tag key hostname
suggest_tagk(prefix) // return tag names (i.e. keys) for all metrics with specific prefix (can be empty)
suggest_tagv(prefix) // return tag values for all metrics with specific prefix (can be empty)
For details on opentsdb metric queries checkout the official [OpenTSDB documentation](http://opentsdb.net/docs/build/html/index.html) If you do not see template variables being populated in `Preview of values` section, you need to enable `tsd.core.meta.enable_realtime_ts` in the OpenTSDB server settings. Also, to populate metadata of the existing time series data in OpenTSDB, you need to run `tsdb uid metasync` on the OpenTSDB server.
\ No newline at end of file
> Note: This is required for the OpenTSDB `lookup` api to work.
For details on opentsdb metric queries checkout the official [OpenTSDB documentation](http://opentsdb.net/docs/build/html/index.html)
...@@ -27,7 +27,7 @@ that is not really the case, or, at least, that it is a lot better than you expe ...@@ -27,7 +27,7 @@ that is not really the case, or, at least, that it is a lot better than you expe
To begin with we are going to install the 3 main components that define our metric stack. Later in the guide we will To begin with we are going to install the 3 main components that define our metric stack. Later in the guide we will
install StatsD, but that is optional. install StatsD, but that is optional.
- Carbon is the graphite ingestion deamon responsible for - Carbon is the graphite ingestion daemon responsible for
receiving metrics and storing them. receiving metrics and storing them.
- Graphite-api is light weight version of graphite-web with only the HTTP api and is - Graphite-api is light weight version of graphite-web with only the HTTP api and is
responsible for executing metric queries. responsible for executing metric queries.
...@@ -90,7 +90,7 @@ pattern = .* ...@@ -90,7 +90,7 @@ pattern = .*
retentions = 10s:1d,1m:7d,10m:1y retentions = 10s:1d,1m:7d,10m:1y
``` ```
This config specifies the resolution of metrics and the retention periods. For example for all metrics begining with the word `carbon` receive metrics every minute and store for 30 days, then This config specifies the resolution of metrics and the retention periods. For example for all metrics beginning with the word `carbon` receive metrics every minute and store for 30 days, then
roll them up into 10 minute buckets and store those for 1 year, then roll those up into 1 hour buckets and store those for 5 years. For all other metrics roll them up into 10 minute buckets and store those for 1 year, then roll those up into 1 hour buckets and store those for 5 years. For all other metrics
the default rule will be applied with other retention periods. the default rule will be applied with other retention periods.
...@@ -206,7 +206,7 @@ Reload supervisor ...@@ -206,7 +206,7 @@ Reload supervisor
supervisorctl reload supervisorctl reload
A carbon-cache deamon and graphite-api should now be running. Type `supervisorctl status` to verify that they are running. You can A carbon-cache daemon and graphite-api should now be running. Type `supervisorctl status` to verify that they are running. You can
also open `http://your_server_ip:8888/metrics/find?query?*` in your browser. You should see a json snippet. also open `http://your_server_ip:8888/metrics/find?query?*` in your browser. You should see a json snippet.
...@@ -243,12 +243,12 @@ Open http://your_server_ip:3000 in your browser and login with the default user ...@@ -243,12 +243,12 @@ Open http://your_server_ip:3000 in your browser and login with the default user
- Select `Add Panel` > `Graph` from the row menu - Select `Add Panel` > `Graph` from the row menu
- An empty graph panel should appear with title `no title (click here)`. Click on this title and then `Edit` - An empty graph panel should appear with title `no title (click here)`. Click on this title and then `Edit`
- This will open the graph in edit mode and take you to the metrics tab. - This will open the graph in edit mode and take you to the metrics tab.
- There is one query already added (asigned letter A) but it is empty. - There is one query already added (assigned letter A) but it is empty.
- Click on `select metric` to pick the first graphite metric node. A new `select metric` link will appear until you reached a leaf node. - Click on `select metric` to pick the first graphite metric node. A new `select metric` link will appear until you reached a leaf node.
- Try picking the metric paths for `carbon.agents.<server name>.cpuUsage`, you should now see a line appear in the graph! - Try picking the metric paths for `carbon.agents.<server name>.cpuUsage`, you should now see a line appear in the graph!
## Writing metrics to Graphite ## Writing metrics to Graphite
Graphite has the simples metric write protocol imaginable. Something that has surely contributed to its wide adoption by metric Graphite has the simplest metric write protocol imaginable. Something that has surely contributed to its wide adoption by metric
frameworks and numerous integrations. frameworks and numerous integrations.
prod.server1.requests.count 10 1398969187 prod.server1.requests.count 10 1398969187
......
...@@ -67,8 +67,8 @@ func init() { ...@@ -67,8 +67,8 @@ func init() {
func handleGetRegions(req *cwRequest, c *middleware.Context) { func handleGetRegions(req *cwRequest, c *middleware.Context) {
regions := []string{ regions := []string{
"us-west-2", "us-west-1", "eu-west-1", "eu-central-1", "ap-southeast-1", "us-east-1", "us-west-2", "us-west-1", "eu-west-1", "eu-central-1", "ap-southeast-1",
"ap-southeast-2", "ap-northeast-1", "sa-east-1", "ap-southeast-2", "ap-northeast-1", "sa-east-1", "cn-north-1",
} }
result := []interface{}{} result := []interface{}{}
......
...@@ -321,7 +321,7 @@ func DeleteUser(cmd *m.DeleteUserCommand) error { ...@@ -321,7 +321,7 @@ func DeleteUser(cmd *m.DeleteUserCommand) error {
return inTransaction(func(sess *xorm.Session) error { return inTransaction(func(sess *xorm.Session) error {
deletes := []string{ deletes := []string{
"DELETE FROM star WHERE user_id = ?", "DELETE FROM star WHERE user_id = ?",
"DELETE FROM user WHERE id = ?", "DELETE FROM " + dialect.Quote("user") + " WHERE id = ?",
} }
for _, sql := range deletes { for _, sql := range deletes {
......
...@@ -10,6 +10,6 @@ datasource annotationQuery changed. now single options parameter with: ...@@ -10,6 +10,6 @@ datasource annotationQuery changed. now single options parameter with:
2.5 changed the `range` parameter in the `datasource.query` function's options parameter. This 2.5 changed the `range` parameter in the `datasource.query` function's options parameter. This
parameter now holds a parsed range with `moment` dates `form` and `to`. To get parameter now holds a parsed range with `moment` dates `form` and `to`. To get
millisecond epoc from a `moment` you the function `valueOf`. The raw date range as represented millisecond epoch from a `moment` you the function `valueOf`. The raw date range as represented
internally in grafana (which may be relative expressions like `now-5h`) is included in the internally in grafana (which may be relative expressions like `now-5h`) is included in the
new property `rangeRaw` (on the options object). new property `rangeRaw` (on the options object).
...@@ -80,8 +80,8 @@ function (angular, _, dateMath) { ...@@ -80,8 +80,8 @@ function (angular, _, dateMath) {
return backendSrv.datasourceRequest(options); return backendSrv.datasourceRequest(options);
}; };
OpenTSDBDatasource.prototype._performSuggestQuery = function(query) { OpenTSDBDatasource.prototype._performSuggestQuery = function(query, type) {
return this._get('/api/suggest', {type: 'metrics', q: query, max: 1000}).then(function(result) { return this._get('/api/suggest', {type: type, q: query, max: 1000}).then(function(result) {
return result.data; return result.data;
}); });
}; };
...@@ -150,10 +150,12 @@ function (angular, _, dateMath) { ...@@ -150,10 +150,12 @@ function (angular, _, dateMath) {
var metrics_regex = /metrics\((.*)\)/; var metrics_regex = /metrics\((.*)\)/;
var tag_names_regex = /tag_names\((.*)\)/; var tag_names_regex = /tag_names\((.*)\)/;
var tag_values_regex = /tag_values\((.*),\s?(.*)\)/; var tag_values_regex = /tag_values\((.*),\s?(.*)\)/;
var tag_names_suggest_regex = /suggest_tagk\((.*)\)/;
var tag_values_suggest_regex = /suggest_tagv\((.*)\)/;
var metrics_query = interpolated.match(metrics_regex); var metrics_query = interpolated.match(metrics_regex);
if (metrics_query) { if (metrics_query) {
return this._performSuggestQuery(metrics_query[1]).then(responseTransform); return this._performSuggestQuery(metrics_query[1], 'metrics').then(responseTransform);
} }
var tag_names_query = interpolated.match(tag_names_regex); var tag_names_query = interpolated.match(tag_names_regex);
...@@ -166,6 +168,16 @@ function (angular, _, dateMath) { ...@@ -166,6 +168,16 @@ function (angular, _, dateMath) {
return this._performMetricKeyValueLookup(tag_values_query[1], tag_values_query[2]).then(responseTransform); return this._performMetricKeyValueLookup(tag_values_query[1], tag_values_query[2]).then(responseTransform);
} }
var tag_names_suggest_query = interpolated.match(tag_names_suggest_regex);
if (tag_names_suggest_query) {
return this._performSuggestQuery(tag_names_suggest_query[1], 'tagk').then(responseTransform);
}
var tag_values_suggest_query = interpolated.match(tag_values_suggest_regex);
if (tag_values_suggest_query) {
return this._performSuggestQuery(tag_values_suggest_query[1], 'tagv').then(responseTransform);
}
return $q.when([]); return $q.when([]);
}; };
......
...@@ -162,20 +162,20 @@ ...@@ -162,20 +162,20 @@
<editor-checkbox text="Counter" model="target.isCounter" change="targetBlur()"></editor-checkbox> <editor-checkbox text="Counter" model="target.isCounter" change="targetBlur()"></editor-checkbox>
</li> </li>
<li class="tight-form-item" ng-hide="!target.isCounter"> <li class="tight-form-item" ng-hide="!target.isCounter || !target.shouldComputeRate">
Counter Max: Counter Max:
</li> </li>
<li ng-hide="!target.isCounter"> <li ng-hide="!target.isCounter || !target.shouldComputeRate">
<input type="text" class="tight-form-input input-small" ng-disabled="!target.shouldComputeRate" <input type="text" class="tight-form-input input-small" ng-disabled="!target.shouldComputeRate"
ng-model="target.counterMax" spellcheck='false' ng-model="target.counterMax" spellcheck='false'
placeholder="max value" ng-model-onblur placeholder="max value" ng-model-onblur
ng-blur="targetBlur()"></input> ng-blur="targetBlur()"></input>
</li> </li>
<li class="tight-form-item" ng-hide="!target.isCounter"> <li class="tight-form-item" ng-hide="!target.isCounter || !target.shouldComputeRate">
Reset Value: Reset Value:
</li> </li>
<li ng-hide="!target.isCounter"> <li ng-hide="!target.isCounter || !target.shouldComputeRate">
<input type="text" class="tight-form-input input-small" ng-disabled="!target.shouldComputeRate" <input type="text" class="tight-form-input input-small" ng-disabled="!target.shouldComputeRate"
ng-model="target.counterResetValue" spellcheck='false' ng-model="target.counterResetValue" spellcheck='false'
placeholder="reset value" ng-model-onblur placeholder="reset value" ng-model-onblur
......
...@@ -48,13 +48,13 @@ function (angular, _, kbn) { ...@@ -48,13 +48,13 @@ function (angular, _, kbn) {
}; };
$scope.suggestTagKeys = function(query, callback) { $scope.suggestTagKeys = function(query, callback) {
$scope.datasource.metricFindQuery('tag_names(' + $scope.target.metric + ')') $scope.datasource.metricFindQuery('suggest_tagk(' + query + ')')
.then($scope.getTextValues) .then($scope.getTextValues)
.then(callback); .then(callback);
}; };
$scope.suggestTagValues = function(query, callback) { $scope.suggestTagValues = function(query, callback) {
$scope.datasource.metricFindQuery('tag_values(' + $scope.target.metric + ',' + $scope.target.currentTagKey + ')') $scope.datasource.metricFindQuery('suggest_tagv(' + query + ')')
.then($scope.getTextValues) .then($scope.getTextValues)
.then(callback); .then(callback);
}; };
......
...@@ -28,9 +28,11 @@ define([ ...@@ -28,9 +28,11 @@ define([
}); });
it('metrics() should generate api suggest query', function() { it('metrics() should generate api suggest query', function() {
ctx.ds.metricFindQuery('metrics()').then(function(data) { results = data; }); ctx.ds.metricFindQuery('metrics(pew)').then(function(data) { results = data; });
ctx.$rootScope.$apply(); ctx.$rootScope.$apply();
expect(requestOptions.url).to.be('/api/suggest'); expect(requestOptions.url).to.be('/api/suggest');
expect(requestOptions.params.type).to.be('metrics');
expect(requestOptions.params.q).to.be('pew');
}); });
it('tag_names(cpu) should generate looku query', function() { it('tag_names(cpu) should generate looku query', function() {
...@@ -47,6 +49,22 @@ define([ ...@@ -47,6 +49,22 @@ define([
expect(requestOptions.params.m).to.be('cpu{hostname=*}'); expect(requestOptions.params.m).to.be('cpu{hostname=*}');
}); });
it('suggest_tagk() should generate api suggest query', function() {
ctx.ds.metricFindQuery('suggest_tagk(foo)').then(function(data) { results = data; });
ctx.$rootScope.$apply();
expect(requestOptions.url).to.be('/api/suggest');
expect(requestOptions.params.type).to.be('tagk');
expect(requestOptions.params.q).to.be('foo');
});
it('suggest_tagv() should generate api suggest query', function() {
ctx.ds.metricFindQuery('suggest_tagv(bar)').then(function(data) { results = data; });
ctx.$rootScope.$apply();
expect(requestOptions.url).to.be('/api/suggest');
expect(requestOptions.params.type).to.be('tagv');
expect(requestOptions.params.q).to.be('bar');
});
}); });
}); });
}); });
......
{
"name": "angular-native-dragdrop",
"version": "1.1.1",
"homepage": "http://angular-dragdrop.github.io/angular-dragdrop",
"authors": [
"ganarajpr"
],
"description": "Angular HTML5 Drag and Drop directive written in pure with no dependency on JQuery.",
"main": "draganddrop.js",
"keywords": [
"angular",
"drag",
"drop",
"html5"
],
"dependencies": {
"angular": "^1.3"
},
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"_release": "1.1.1",
"_resolution": {
"type": "version",
"tag": "v1.1.1",
"commit": "4ff89cb0aa61070508e935729fb816fd46a58f60"
},
"_source": "git://github.com/angular-dragdrop/angular-dragdrop.git",
"_target": "~1.1.1",
"_originalSource": "angular-native-dragdrop"
}
\ No newline at end of file
/* jshint -W097 */
'use strict';
/* global require */
var jshint = require('gulp-jshint');
var stylish = require('jshint-stylish');
var gulp = require('gulp');
gulp.task('lint', function() {
return gulp.src('./draganddrop.js')
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
gulp.task('default', ['lint']);
The MIT License
Copyright (c) 2015 Ganaraj P R, [Nebithi](http://www.nebithi.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
{
"name": "angular-native-dragdrop",
"version": "1.1.1",
"homepage": "http://angular-dragdrop.github.io/angular-dragdrop",
"authors": [
"ganarajpr"
],
"description": "Angular HTML5 Drag and Drop directive written in pure with no dependency on JQuery.",
"main": "draganddrop.js",
"keywords": [
"angular",
"drag",
"drop",
"html5"
],
"dependencies": {
"angular": "^1.3"
},
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
body {
background-color: #f8f7f8;
}
.heading {
border-bottom: 1px solid #b7b7b7;
padding-bottom: 10px;
margin-bottom: 10px;
}
.topRow {
margin-bottom: 30px;
}
.on-drag-enter {
background-color : #677ba6;
}
.on-drag-enter-custom {
background-color : #d78cc7;
}
.on-drag-hover {
background-color : #3eb352;
}
.on-drag-hover-custom {
background-color : #d7a931;
}
\ No newline at end of file
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>Angular DragDrop (Demo)</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="css/styles.css" />
<script data-require="angular.js@1.4.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js" data-semver="1.4.3"></script>
<script src="http://pc035860.github.io/angular-highlightjs/angular-highlightjs.min.js"></script>
<script src="js/app.js"></script>
<script src="../draganddrop.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
</head>
<body >
<div class="container">
<div class="row topRow">
<h4 class="heading">
Drag and drop between the two lists.
</h4>
</div>
<h3>Beasts</h3>
<p>Left column of beasts is not draggable and accepts both beasts and priests</p>
<hr>
<div class="row" ng-controller="MainCtrl">
<div class="col-xs-6">
<ul ui-on-drop="onDrop($event,$data,men)" drag-enter-class="on-drag-enter-custom"
drop-channel="beasts,priests"
drop-validate="dropValidateHandler($drop, $event, $data)">
<li ui-draggable="false" drag="man" drag-channel="beasts"
on-drop-success="dropSuccessHandler($event,$index,men)"
ng-repeat="man in men track by $index">
{{man}}
</li>
</ul>
</div>
<div class="col-xs-6">
<ul ui-on-drop="onDrop($event,$data,women)"
drop-channel="beasts"
drop-validate="dropValidateHandler($drop, $event, $data)">
<li ui-draggable="true" drag="woman" drag-channel="beasts"
on-drop-success="dropSuccessHandler($event,$index,women)"
ng-repeat="woman in women track by $index">
{{woman}}
</li>
</ul>
</div>
</div>
<hr>
<h3>Priests</h3>
<hr>
<div class="row" ng-controller="MainCtrl">
<div class="col-xs-6">
<ul ui-on-drop="onDrop($event,$data,men)"
drop-channel="priests"
drop-validate="dropValidateHandler($drop, $event, $data)">
<li ui-draggable="true" drag="man"
drag-channel="priests"
on-drop-success="dropSuccessHandler($event,$index,men)"
ng-repeat="man in men track by $index">
{{man}}
</li>
</ul>
</div>
<div class="col-xs-6">
<ul ui-on-drop="onDrop($event,$data,women)"
drop-channel="priests"
drop-validate="dropValidateHandler($drop, $event, $data)">
<li ui-draggable="true" drag="woman"
drag-channel="priests"
on-drop-success="dropSuccessHandler($event,$index,women)"
ng-repeat="woman in women track by $index">
{{woman}}
</li>
</ul>
</div>
</div>
<hr>
<h3>Terrorists</h3>
<p>Each terrorist list item accepts a new terrorist. Shows inserting into a particular
position in an array.</p>
<hr>
<div class="row" ng-controller="MainCtrl">
<div class="col-xs-6">
<ul>
<li ui-draggable="true" drag="man"
drag-channel="terrorists2"
drop-validate="dropValidateHandler($drop, $event, $data)"
drag-hover-class="on-drag-hover-custom"
on-drop-success="dropSuccessHandler($event,$index,men)"
ui-on-drop="onDrop($event,$data,men,$index)" drop-channel="terrorists1"
ng-repeat="man in men track by $index">
{{man}}
</li>
</ul>
</div>
<div class="col-xs-6">
<ul>
<li ui-draggable="true" drag="woman"
drag-channel="terrorists1"
drop-validate="dropValidateHandler($drop, $event, $data)"
drag-hover-class="on-drag-hover-custom"
ui-on-drop="onDrop($event,$data,women,$index)" drop-channel="terrorists2"
on-drop-success="dropSuccessHandler($event,$index,women)"
ng-repeat="woman in women track by $index">
{{woman}}
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
angular.module('app', [
'hljs',
'ang-drag-drop'
]).controller('MainCtrl', function($scope) {
$scope.men = [
'John',
'Jack',
'Mark',
'Ernie',
'Mike (Locked)'
];
$scope.women = [
'Jane',
'Jill',
'Betty',
'Mary'
];
$scope.addText = '';
$scope.dropValidateHandler = function($drop, $event, $data) {
if ($data === 'Mike (Locked)') {
return false;
}
if ($drop.element[0] === $event.srcElement.parentNode) {
// Don't allow moving to same container
return false;
}
return true;
};
$scope.dropSuccessHandler = function($event, index, array) {
array.splice(index, 1);
};
$scope.onDrop = function($event, $data, array, index) {
if (index !== undefined) {
array.splice(index, 0, $data);
} else {
array.push($data);
}
};
});
.content {
margin : 50px auto;
font-size: 1.0em;
line-height: 1.5em;
}
.content a{
color: #677BA6;
cursor: pointer;
}
body {
background-color: #f8f7f8;
}
.jumbotron h1,
.jumbotron p{
font-family: 'Open Sans';
}
.heading{
border-bottom: 1px solid #b7b7b7;
padding-bottom: 10px;
margin-bottom: 10px;
}
.ribbon{
position: fixed;
top : 0;
right : 0;
z-index: 2000;
}
\ No newline at end of file
{
"name": "angular-native-dragdrop",
"version": "1.1.1",
"description": "Angular HTML5 Drag and Drop directive written in pure with no dependency on JQuery.",
"main": "draganddrop.js",
"scripts": {
"test": "gulp"
},
"repository": {
"type": "git",
"url": "https://github.com/angular-dragdrop/angular-dragdrop.git"
},
"author": "ganarajpr",
"license": "MIT",
"bugs": {
"url": "https://github.com/angular-dragdrop/angular-dragdrop/issues"
},
"homepage": "http://angular-dragdrop.github.io/angular-dragdrop",
"devDependencies": {
"gulp": "^3.8.11",
"gulp-jshint": "^1.9.2",
"jshint-stylish": "^1.0.1"
}
}
...@@ -6,6 +6,11 @@ module.exports = function(config,grunt) { ...@@ -6,6 +6,11 @@ module.exports = function(config,grunt) {
var dest = './vendor/phantomjs/phantomjs'; var dest = './vendor/phantomjs/phantomjs';
var confDir = './node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/' var confDir = './node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/'
if (!grunt.file.exists(confDir)) {
// npm 3 or npm 2 with dedupe
confDir = './node_modules/phantomjs/lib/';
}
if (!grunt.file.exists(dest)){ if (!grunt.file.exists(dest)){
var m=grunt.file.read(confDir+"location.js") var m=grunt.file.read(confDir+"location.js")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment