mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Upgraded to angular 1.1.5, refactored filter refreshing, changed panels to destroy scope on hide
This commit is contained in:
parent
a99c81d201
commit
6bdb4f3486
@ -47,7 +47,7 @@ function (angular) {
|
|||||||
|
|
||||||
'<span class="row-button extra" ng-show="panelMeta.loading == true">' +
|
'<span class="row-button extra" ng-show="panelMeta.loading == true">' +
|
||||||
'<span>'+
|
'<span>'+
|
||||||
'<i class="icon-spinner smaller icon-spin icon-large"></i>' +
|
'<i class="icon-spinner icon-spin icon-large"></i>' +
|
||||||
'</span>'+
|
'</span>'+
|
||||||
'</span>' +
|
'</span>' +
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
<div ng-hide="filterSrv.list[id].editing && isEditable(filterSrv.list[id])">
|
<div ng-hide="filterSrv.list[id].editing && isEditable(filterSrv.list[id])">
|
||||||
<ul class="unstyled">
|
<ul class="unstyled">
|
||||||
<li ng-repeat="(key,value) in filterSrv.list[id]" ng-show="show_key(key)"><strong>{{key}}</strong> : {{value}}</li>
|
<li ng-repeat="(key,value) in filterSrv.list[id] track by $index" ng-show="show_key(key)"><strong>{{key}}</strong> : {{value}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="filterSrv.list[id].editing && isEditable(filterSrv.list[id])">
|
<div ng-show="filterSrv.list[id].editing && isEditable(filterSrv.list[id])">
|
||||||
|
@ -33,16 +33,16 @@ function (angular, app, _) {
|
|||||||
|
|
||||||
$scope.remove = function(id) {
|
$scope.remove = function(id) {
|
||||||
filterSrv.remove(id);
|
filterSrv.remove(id);
|
||||||
dashboard.refresh();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This function should be moved to the service
|
||||||
$scope.toggle = function(id) {
|
$scope.toggle = function(id) {
|
||||||
filterSrv.list[id].active = !filterSrv.list[id].active;
|
filterSrv.list[id].active = !filterSrv.list[id].active;
|
||||||
dashboard.refresh();
|
dashboard.refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.refresh = function() {
|
$scope.refresh = function() {
|
||||||
$rootScope.$broadcast('refresh');
|
dashboard.refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.render = function() {
|
$scope.render = function() {
|
||||||
|
@ -312,9 +312,6 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
|||||||
to:moment.utc(_to),
|
to:moment.utc(_to),
|
||||||
field:$scope.panel.time_field
|
field:$scope.panel.time_field
|
||||||
});
|
});
|
||||||
|
|
||||||
dashboard.refresh();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// I really don't like this function, too much dom manip. Break out into directive?
|
// I really don't like this function, too much dom manip. Break out into directive?
|
||||||
@ -449,7 +446,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
|||||||
scope.plot = $.plot(elem, scope.data, options);
|
scope.plot = $.plot(elem, scope.data, options);
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log(e);
|
// Nothing to do here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +499,6 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
|||||||
to : moment.utc(ranges.xaxis.to),
|
to : moment.utc(ranges.xaxis.to),
|
||||||
field : scope.panel.time_field
|
field : scope.panel.time_field
|
||||||
});
|
});
|
||||||
dashboard.refresh();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -121,7 +121,6 @@ function (angular, app, _, $) {
|
|||||||
|
|
||||||
$scope.build_search = function(field,value) {
|
$scope.build_search = function(field,value) {
|
||||||
filterSrv.set({type:'querystring',mandate:'must',query:field+":"+value});
|
filterSrv.set({type:'querystring',mandate:'must',query:field+":"+value});
|
||||||
dashboard.refresh();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -175,7 +175,7 @@ define([
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.directive('pie', function(querySrv, filterSrv, dashboard) {
|
module.directive('pie', function(querySrv, filterSrv) {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function(scope, elem) {
|
link: function(scope, elem) {
|
||||||
@ -270,7 +270,6 @@ define([
|
|||||||
}
|
}
|
||||||
if(scope.panel.mode === 'terms') {
|
if(scope.panel.mode === 'terms') {
|
||||||
filterSrv.set({type:'terms',field:scope.panel.query.field,value:object.series.label});
|
filterSrv.set({type:'terms',field:scope.panel.query.field,value:object.series.label});
|
||||||
dashboard.refresh();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -41,4 +41,4 @@
|
|||||||
<div class="progress" ng-show="micropanel.grouped">
|
<div class="progress" ng-show="micropanel.grouped">
|
||||||
<div ng-repeat='field in micropanel.values' bs-tooltip="field[0]+' ('+percent(field[1],data.length)+')'" class="bar {{micropanelColor($index)}}" ng-style="{width: percent(field[1],data.length)};"></div>
|
<div ng-repeat='field in micropanel.values' bs-tooltip="field[0]+' ('+percent(field[1],data.length)+')'" class="bar {{micropanelColor($index)}}" ng-style="{width: percent(field[1],data.length)};"></div>
|
||||||
</div>
|
</div>
|
||||||
<span ng-repeat='(field,count) in micropanel.related'><a ng-click="toggle_field(field)">{{field}}</a> ({{Math.round((count / micropanel.count) * 100)}}%), </span>
|
<span ng-repeat='(field,count) in micropanel.related track by $index'><a ng-click="toggle_field(field)">{{field}}</a> ({{Math.round((count / micropanel.count) * 100)}}%), </span>
|
@ -160,14 +160,12 @@ function (angular, app, _, kbn, moment) {
|
|||||||
} else {
|
} else {
|
||||||
query = angular.toJson(value);
|
query = angular.toJson(value);
|
||||||
}
|
}
|
||||||
filterSrv.set({type:'field',field:field,query:query,mandate:(negate ? 'mustNot':'must')});
|
|
||||||
$scope.panel.offset = 0;
|
$scope.panel.offset = 0;
|
||||||
dashboard.refresh();
|
filterSrv.set({type:'field',field:field,query:query,mandate:(negate ? 'mustNot':'must')});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.fieldExists = function(field,mandate) {
|
$scope.fieldExists = function(field,mandate) {
|
||||||
filterSrv.set({type:'exists',field:field,mandate:mandate});
|
filterSrv.set({type:'exists',field:field,mandate:mandate});
|
||||||
dashboard.refresh();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.get_data = function(segment,query_id) {
|
$scope.get_data = function(segment,query_id) {
|
||||||
|
@ -143,7 +143,6 @@ function (angular, app, _, $, kbn) {
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dashboard.refresh();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.set_refresh = function (state) {
|
$scope.set_refresh = function (state) {
|
||||||
|
@ -87,9 +87,6 @@ function (angular, app, _, moment, kbn) {
|
|||||||
set_time_filter($scope.time);
|
set_time_filter($scope.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboard.refresh();
|
|
||||||
|
|
||||||
|
|
||||||
// Start refresh timer if enabled
|
// Start refresh timer if enabled
|
||||||
if ($scope.panel.refresh.enable) {
|
if ($scope.panel.refresh.enable) {
|
||||||
$scope.set_interval($scope.panel.refresh.interval);
|
$scope.set_interval($scope.panel.refresh.interval);
|
||||||
@ -219,8 +216,7 @@ function (angular, app, _, moment, kbn) {
|
|||||||
// Update internal time object
|
// Update internal time object
|
||||||
|
|
||||||
// Remove all other time filters
|
// Remove all other time filters
|
||||||
filterSrv.removeByType('time');
|
filterSrv.removeByType('time',true);
|
||||||
|
|
||||||
|
|
||||||
$scope.time = $scope.time_calc();
|
$scope.time = $scope.time_calc();
|
||||||
$scope.time.field = $scope.panel.timefield;
|
$scope.time.field = $scope.panel.timefield;
|
||||||
@ -228,15 +224,14 @@ function (angular, app, _, moment, kbn) {
|
|||||||
update_panel();
|
update_panel();
|
||||||
set_time_filter($scope.time);
|
set_time_filter($scope.time);
|
||||||
|
|
||||||
dashboard.refresh();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
$scope.$watch('panel.mode', $scope.time_apply);
|
|
||||||
|
//$scope.$watch('panel.mode', $scope.time_apply);
|
||||||
|
|
||||||
function set_time_filter(time) {
|
function set_time_filter(time) {
|
||||||
time.type = 'time';
|
time.type = 'time';
|
||||||
// Clear all time filters, set a new one
|
// Clear all time filters, set a new one
|
||||||
filterSrv.removeByType('time');
|
filterSrv.removeByType('time',true);
|
||||||
$scope.panel.filter_id = filterSrv.set(compile_time(time));
|
$scope.panel.filter_id = filterSrv.set(compile_time(time));
|
||||||
return $scope.panel.filter_id;
|
return $scope.panel.filter_id;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid" style="padding-top:0px" ng-hide="row.collapse">
|
<div class="row-fluid" style="padding-top:0px" ng-if="!row.collapse">
|
||||||
|
|
||||||
<!-- Panels -->
|
<!-- Panels -->
|
||||||
<div ng-repeat="(name, panel) in row.panels|filter:isPanel" ng-hide="panel.span == 0 || panel.hide" class="span{{panel.span}} panel nospace" style="min-height:{{row.height}}; position:relative" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:$index,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver(true)',onOut:'panelMoveOut'}">
|
<div ng-repeat="(name, panel) in row.panels|filter:isPanel" ng-hide="panel.span == 0 || panel.hide" class="span{{panel.span}} panel nospace" style="min-height:{{row.height}}; position:relative" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:$index,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver(true)',onOut:'panelMoveOut'}">
|
||||||
@ -52,7 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-hide="(12-rowSpan(row)) < 1 || !dashboard.current.panel_hints" class="panel span{{(12-rowSpan(row))}}" ng-class="{'dragInProgress':dashboard.panelDragging}" style="height:{{row.height}};" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:row.panels.length,onDrop:'panelMoveDrop({{(12-rowSpan(row))}})',onOver:'panelMoveOver(false)',onOut:'panelMoveOut'}">
|
<div ng-hide="(12-rowSpan(row)) < 1 || !dashboard.current.panel_hints" class="panel span{{(12-rowSpan(row))}}" ng-class="{'dragInProgress':dashboard.panelDragging}" style="height:{{row.height}};" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:row.panels.length,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver',onOut:'panelMoveOut'}">
|
||||||
|
|
||||||
<span bs-modal="'app/partials/roweditor.html'" ng-show="row.editable && !dashboard.panelDragging">
|
<span bs-modal="'app/partials/roweditor.html'" ng-show="row.editable && !dashboard.panelDragging">
|
||||||
<i ng-hide="rowSpan(row) == 0" class="pointer icon-plus-sign" ng-click="editor.index = 2" bs-tooltip="'Add a panel to this row'" data-placement="right"></i>
|
<i ng-hide="rowSpan(row) == 0" class="pointer icon-plus-sign" ng-click="editor.index = 2" bs-tooltip="'Add a panel to this row'" data-placement="right"></i>
|
||||||
|
@ -7,7 +7,7 @@ define([
|
|||||||
|
|
||||||
var module = angular.module('kibana.services');
|
var module = angular.module('kibana.services');
|
||||||
|
|
||||||
module.service('filterSrv', function(dashboard, ejsResource) {
|
module.service('filterSrv', function(dashboard, ejsResource, $rootScope, $timeout) {
|
||||||
// Create an object to hold our service state on the dashboard
|
// Create an object to hold our service state on the dashboard
|
||||||
dashboard.current.services.filter = dashboard.current.services.filter || {};
|
dashboard.current.services.filter = dashboard.current.services.filter || {};
|
||||||
|
|
||||||
@ -44,19 +44,20 @@ define([
|
|||||||
|
|
||||||
// This is used both for adding filters and modifying them.
|
// This is used both for adding filters and modifying them.
|
||||||
// If an id is passed, the filter at that id is updated
|
// If an id is passed, the filter at that id is updated
|
||||||
this.set = function(filter,id) {
|
this.set = function(filter,id,noRefresh) {
|
||||||
|
var _r;
|
||||||
_.defaults(filter,{mandate:'must'});
|
_.defaults(filter,{mandate:'must'});
|
||||||
filter.active = true;
|
filter.active = true;
|
||||||
if(!_.isUndefined(id)) {
|
if(!_.isUndefined(id)) {
|
||||||
if(!_.isUndefined(self.list[id])) {
|
if(!_.isUndefined(self.list[id])) {
|
||||||
_.extend(self.list[id],filter);
|
_.extend(self.list[id],filter);
|
||||||
return id;
|
_r = id;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
_r = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(_.isUndefined(filter.type)) {
|
if(_.isUndefined(filter.type)) {
|
||||||
return false;
|
_r = false;
|
||||||
} else {
|
} else {
|
||||||
var _id = nextId();
|
var _id = nextId();
|
||||||
var _filter = {
|
var _filter = {
|
||||||
@ -66,9 +67,54 @@ define([
|
|||||||
_.defaults(filter,_filter);
|
_.defaults(filter,_filter);
|
||||||
self.list[_id] = filter;
|
self.list[_id] = filter;
|
||||||
self.ids.push(_id);
|
self.ids.push(_id);
|
||||||
return _id;
|
_r = _id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!$rootScope.$$phase) {
|
||||||
|
$rootScope.$apply();
|
||||||
|
}
|
||||||
|
if(noRefresh !== true) {
|
||||||
|
$timeout(function(){
|
||||||
|
dashboard.refresh();
|
||||||
|
},0);
|
||||||
|
}
|
||||||
|
return _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.remove = function(id,noRefresh) {
|
||||||
|
var _r;
|
||||||
|
if(!_.isUndefined(self.list[id])) {
|
||||||
|
delete self.list[id];
|
||||||
|
// This must happen on the full path also since _.without returns a copy
|
||||||
|
self.ids = dashboard.current.services.filter.ids = _.without(self.ids,id);
|
||||||
|
_f.idQueue.unshift(id);
|
||||||
|
_f.idQueue.sort(function(v,k){return v-k;});
|
||||||
|
_r = true;
|
||||||
|
} else {
|
||||||
|
_r = false;
|
||||||
|
}
|
||||||
|
if(!$rootScope.$$phase) {
|
||||||
|
$rootScope.$apply();
|
||||||
|
}
|
||||||
|
if(noRefresh !== true) {
|
||||||
|
$timeout(function(){
|
||||||
|
dashboard.refresh();
|
||||||
|
},0);
|
||||||
|
}
|
||||||
|
return _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.removeByType = function(type,noRefresh) {
|
||||||
|
var ids = self.idsByType(type);
|
||||||
|
_.each(ids,function(id) {
|
||||||
|
self.remove(id,true);
|
||||||
|
});
|
||||||
|
if(noRefresh !== true) {
|
||||||
|
$timeout(function(){
|
||||||
|
dashboard.refresh();
|
||||||
|
},0);
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getBoolFilter = function(ids) {
|
this.getBoolFilter = function(ids) {
|
||||||
@ -106,6 +152,7 @@ define([
|
|||||||
case 'time':
|
case 'time':
|
||||||
return ejs.RangeFilter(filter.field)
|
return ejs.RangeFilter(filter.field)
|
||||||
.from(filter.from.valueOf())
|
.from(filter.from.valueOf())
|
||||||
|
//.from("now-1d")
|
||||||
.to(filter.to.valueOf());
|
.to(filter.to.valueOf());
|
||||||
case 'range':
|
case 'range':
|
||||||
return ejs.RangeFilter(filter.field)
|
return ejs.RangeFilter(filter.field)
|
||||||
@ -130,14 +177,6 @@ define([
|
|||||||
return _.pick(self.list,self.idsByType(type,inactive));
|
return _.pick(self.list,self.idsByType(type,inactive));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeByType = function(type) {
|
|
||||||
var ids = self.idsByType(type);
|
|
||||||
_.each(ids,function(id) {
|
|
||||||
self.remove(id);
|
|
||||||
});
|
|
||||||
return ids;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.idsByType = function(type,inactive) {
|
this.idsByType = function(type,inactive) {
|
||||||
var _require = inactive ? {type:type} : {type:type,active:true};
|
var _require = inactive ? {type:type} : {type:type,active:true};
|
||||||
return _.pluck(_.where(self.list,_require),'id');
|
return _.pluck(_.where(self.list,_require),'id');
|
||||||
@ -171,20 +210,6 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.remove = function(id) {
|
|
||||||
if(!_.isUndefined(self.list[id])) {
|
|
||||||
delete self.list[id];
|
|
||||||
// This must happen on the full path also since _.without returns a copy
|
|
||||||
self.ids = dashboard.current.services.filter.ids = _.without(self.ids,id);
|
|
||||||
_f.idQueue.unshift(id);
|
|
||||||
_f.idQueue.sort(function(v,k){return v-k;});
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var nextId = function() {
|
var nextId = function() {
|
||||||
if(_f.idQueue.length > 0) {
|
if(_f.idQueue.length > 0) {
|
||||||
return _f.idQueue.shift();
|
return _f.idQueue.shift();
|
||||||
|
54
src/vendor/angular/angular-sanitize.js
vendored
54
src/vendor/angular/angular-sanitize.js
vendored
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.0.8
|
* @license AngularJS v1.1.5
|
||||||
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
@ -10,25 +10,6 @@
|
|||||||
* @ngdoc overview
|
* @ngdoc overview
|
||||||
* @name ngSanitize
|
* @name ngSanitize
|
||||||
* @description
|
* @description
|
||||||
*
|
|
||||||
* The `ngSanitize` module provides functionality to sanitize HTML.
|
|
||||||
*
|
|
||||||
* # Installation
|
|
||||||
* As a separate module, it must be loaded after Angular core is loaded; otherwise, an 'Uncaught Error:
|
|
||||||
* No module: ngSanitize' runtime error will occur.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <script src="angular.js"></script>
|
|
||||||
* <script src="angular-sanitize.js"></script>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* # Usage
|
|
||||||
* To make sure the module is available to your application, declare it as a dependency of you application
|
|
||||||
* module.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* angular.module('app', ['ngSanitize']);
|
|
||||||
* </pre>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -148,7 +129,7 @@ var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:
|
|||||||
BEGING_END_TAGE_REGEXP = /^<\s*\//,
|
BEGING_END_TAGE_REGEXP = /^<\s*\//,
|
||||||
COMMENT_REGEXP = /<!--(.*?)-->/g,
|
COMMENT_REGEXP = /<!--(.*?)-->/g,
|
||||||
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
|
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
|
||||||
URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/i,
|
URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/,
|
||||||
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
|
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
|
||||||
|
|
||||||
|
|
||||||
@ -302,10 +283,10 @@ function htmlParser( html, handler ) {
|
|||||||
|
|
||||||
var attrs = {};
|
var attrs = {};
|
||||||
|
|
||||||
rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
|
rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {
|
||||||
var value = doubleQuotedValue
|
var value = doubleQuotedValue
|
||||||
|| singleQuotedValue
|
|| singleQoutedValue
|
||||||
|| unquotedValue
|
|| unqoutedValue
|
||||||
|| '';
|
|| '';
|
||||||
|
|
||||||
attrs[name] = decodeEntities(value);
|
attrs[name] = decodeEntities(value);
|
||||||
@ -452,6 +433,7 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
|
|||||||
* plain email address links.
|
* plain email address links.
|
||||||
*
|
*
|
||||||
* @param {string} text Input text.
|
* @param {string} text Input text.
|
||||||
|
* @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
|
||||||
* @returns {string} Html-linkified text.
|
* @returns {string} Html-linkified text.
|
||||||
*
|
*
|
||||||
* @usage
|
* @usage
|
||||||
@ -468,6 +450,7 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
|
|||||||
'mailto:us@somewhere.org,\n'+
|
'mailto:us@somewhere.org,\n'+
|
||||||
'another@somewhere.org,\n'+
|
'another@somewhere.org,\n'+
|
||||||
'and one more: ftp://127.0.0.1/.';
|
'and one more: ftp://127.0.0.1/.';
|
||||||
|
$scope.snippetWithTarget = 'http://angularjs.org/';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div ng-controller="Ctrl">
|
<div ng-controller="Ctrl">
|
||||||
@ -487,6 +470,15 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
|
|||||||
<div ng-bind-html="snippet | linky"></div>
|
<div ng-bind-html="snippet | linky"></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr id="linky-target">
|
||||||
|
<td>linky target</td>
|
||||||
|
<td>
|
||||||
|
<pre><div ng-bind-html="snippetWithTarget | linky:'_blank'"><br></div></pre>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr id="escaped-html">
|
<tr id="escaped-html">
|
||||||
<td>no filter</td>
|
<td>no filter</td>
|
||||||
<td><pre><div ng-bind="snippet"><br></div></pre></td>
|
<td><pre><div ng-bind="snippet"><br></div></pre></td>
|
||||||
@ -519,6 +511,11 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
|
|||||||
toBe('new <a href="http://link">http://link</a>.');
|
toBe('new <a href="http://link">http://link</a>.');
|
||||||
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
|
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work with the target property', function() {
|
||||||
|
expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
|
||||||
|
toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
|
||||||
|
});
|
||||||
</doc:scenario>
|
</doc:scenario>
|
||||||
</doc:example>
|
</doc:example>
|
||||||
*/
|
*/
|
||||||
@ -526,7 +523,7 @@ angular.module('ngSanitize').filter('linky', function() {
|
|||||||
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
|
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
|
||||||
MAILTO_REGEXP = /^mailto:/;
|
MAILTO_REGEXP = /^mailto:/;
|
||||||
|
|
||||||
return function(text) {
|
return function(text, target) {
|
||||||
if (!text) return text;
|
if (!text) return text;
|
||||||
var match;
|
var match;
|
||||||
var raw = text;
|
var raw = text;
|
||||||
@ -535,6 +532,10 @@ angular.module('ngSanitize').filter('linky', function() {
|
|||||||
var writer = htmlSanitizeWriter(html);
|
var writer = htmlSanitizeWriter(html);
|
||||||
var url;
|
var url;
|
||||||
var i;
|
var i;
|
||||||
|
var properties = {};
|
||||||
|
if (angular.isDefined(target)) {
|
||||||
|
properties.target = target;
|
||||||
|
}
|
||||||
while ((match = raw.match(LINKY_URL_REGEXP))) {
|
while ((match = raw.match(LINKY_URL_REGEXP))) {
|
||||||
// We can not end in these as they are sometimes found at the end of the sentence
|
// We can not end in these as they are sometimes found at the end of the sentence
|
||||||
url = match[0];
|
url = match[0];
|
||||||
@ -542,7 +543,8 @@ angular.module('ngSanitize').filter('linky', function() {
|
|||||||
if (match[2] == match[3]) url = 'mailto:' + url;
|
if (match[2] == match[3]) url = 'mailto:' + url;
|
||||||
i = match.index;
|
i = match.index;
|
||||||
writer.chars(raw.substr(0, i));
|
writer.chars(raw.substr(0, i));
|
||||||
writer.start('a', {href:url});
|
properties.href = url;
|
||||||
|
writer.start('a', properties);
|
||||||
writer.chars(match[0].replace(MAILTO_REGEXP, ''));
|
writer.chars(match[0].replace(MAILTO_REGEXP, ''));
|
||||||
writer.end('a');
|
writer.end('a');
|
||||||
raw = raw.substring(i + match[0].length);
|
raw = raw.substring(i + match[0].length);
|
||||||
|
4268
src/vendor/angular/angular.js
vendored
4268
src/vendor/angular/angular.js
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user