mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-20 12:21:52 +00:00
feat(bootstrap): support code prettify and dropdown from bootstrap
This commit is contained in:
parent
cef3535c16
commit
c4fa487250
8 changed files with 6230 additions and 0 deletions
4
Rakefile
4
Rakefile
|
|
@ -124,6 +124,10 @@ task :package => [:clean, :compile, :docs] do
|
||||||
path_to('angular.min.js'),
|
path_to('angular.min.js'),
|
||||||
path_to('angular-loader.js'),
|
path_to('angular-loader.js'),
|
||||||
path_to('angular-loader.min.js'),
|
path_to('angular-loader.min.js'),
|
||||||
|
path_to('angular-bootstrap.js'),
|
||||||
|
path_to('angular-bootstrap.min.js'),
|
||||||
|
path_to('angular-bootstrap-prettify.js'),
|
||||||
|
path_to('angular-bootstrap-prettify.min.js'),
|
||||||
path_to('angular-mocks.js'),
|
path_to('angular-mocks.js'),
|
||||||
path_to('angular-cookies.js'),
|
path_to('angular-cookies.js'),
|
||||||
path_to('angular-cookies.min.js'),
|
path_to('angular-cookies.min.js'),
|
||||||
|
|
|
||||||
264
src/bootstrap/bootstrap-prettify.js
vendored
Normal file
264
src/bootstrap/bootstrap-prettify.js
vendored
Normal file
|
|
@ -0,0 +1,264 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var directive = {};
|
||||||
|
var service = { value: {} };
|
||||||
|
|
||||||
|
var DEPENDENCIES = {
|
||||||
|
'angular.js': 'http://code.angularjs.org/angular-' + angular.version.full + '.min.js',
|
||||||
|
'angular-resource.js': 'http://code.angularjs.org/angular-resource-' + angular.version.full + '.min.js',
|
||||||
|
'angular-sanitize.js': 'http://code.angularjs.org/angular-sanitize-' + angular.version.full + '.min.js',
|
||||||
|
'angular-cookies.js': 'http://code.angularjs.org/angular-cookies-' + angular.version.full + '.min.js'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function escape(text) {
|
||||||
|
return text.
|
||||||
|
replace(/\&/g, '&').
|
||||||
|
replace(/\</g, '<').
|
||||||
|
replace(/\>/g, '>').
|
||||||
|
replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
directive.jsFiddle = function(getEmbededTemplate, escape, script) {
|
||||||
|
return {
|
||||||
|
terminal: true,
|
||||||
|
link: function(scope, element, attr) {
|
||||||
|
var name = '',
|
||||||
|
stylesheet = '<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">\n',
|
||||||
|
fields = {
|
||||||
|
html: '',
|
||||||
|
css: '',
|
||||||
|
js: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
angular.forEach(attr.jsFiddle.split(' '), function(file, index) {
|
||||||
|
var fileType = file.split('.')[1];
|
||||||
|
|
||||||
|
if (fileType == 'html') {
|
||||||
|
if (index == 0) {
|
||||||
|
fields[fileType] +=
|
||||||
|
'<div ng-app' + (attr.module ? '="' + attr.module + '"' : '') + '>\n' +
|
||||||
|
getEmbededTemplate(file, 2);
|
||||||
|
} else {
|
||||||
|
fields[fileType] += '\n\n\n <!-- CACHE FILE: ' + file + ' -->\n' +
|
||||||
|
' <script type="text/ng-template" id="' + file + '">\n' +
|
||||||
|
getEmbededTemplate(file, 4) +
|
||||||
|
' </script>\n';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fields[fileType] += getEmbededTemplate(file) + '\n';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fields.html += '</div>\n';
|
||||||
|
|
||||||
|
element.html(
|
||||||
|
'<form class="jsfiddle" method="post" action="http://jsfiddle.net/api/post/library/pure/" target="_blank">' +
|
||||||
|
hiddenField('title', 'AngularJS Example: ' + name) +
|
||||||
|
hiddenField('css', '</style> <!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --> \n' +
|
||||||
|
stylesheet +
|
||||||
|
script.angular +
|
||||||
|
(attr.resource ? script.resource : '') +
|
||||||
|
'<style>\n' +
|
||||||
|
fields.css) +
|
||||||
|
hiddenField('html', fields.html) +
|
||||||
|
hiddenField('js', fields.js) +
|
||||||
|
'<button class="btn btn-primary"><i class="icon-white icon-pencil"></i> Edit Me</button>' +
|
||||||
|
'</form>');
|
||||||
|
|
||||||
|
function hiddenField(name, value) {
|
||||||
|
return '<input type="hidden" name="' + name + '" value="' + escape(value) + '">';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
directive.code = function() {
|
||||||
|
return {restrict: 'E', terminal: true};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
directive.prettyprint = ['reindentCode', function(reindentCode) {
|
||||||
|
return {
|
||||||
|
restrict: 'C',
|
||||||
|
terminal: true,
|
||||||
|
compile: function(element) {
|
||||||
|
element.html(window.prettyPrintOne(reindentCode(element.html()), undefined, true));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
directive.ngSetText = ['getEmbededTemplate', function(getEmbededTemplate) {
|
||||||
|
return {
|
||||||
|
restrict: 'CA',
|
||||||
|
priority: 10,
|
||||||
|
compile: function(element, attr) {
|
||||||
|
element.text(getEmbededTemplate(attr.ngSetText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
|
directive.ngHtmlWrap = ['reindentCode', 'templateMerge', function(reindentCode, templateMerge) {
|
||||||
|
return {
|
||||||
|
compile: function(element, attr) {
|
||||||
|
var properties = {
|
||||||
|
head: '',
|
||||||
|
module: '',
|
||||||
|
body: reindentCode(element.text(), 4)
|
||||||
|
},
|
||||||
|
html = "<!doctype html>\n<html ng-app{{module}}>\n <head>\n{{head}} </head>\n <body>\n{{body}} </body>\n</html>";
|
||||||
|
|
||||||
|
angular.forEach((attr.ngHtmlWrap || '').split(' '), function(dep) {
|
||||||
|
if (!dep) return;
|
||||||
|
dep = DEPENDENCIES[dep] || dep;
|
||||||
|
|
||||||
|
var ext = dep.split(/\./).pop();
|
||||||
|
|
||||||
|
if (ext == 'css') {
|
||||||
|
properties.head += ' <link rel="stylesheet" href="' + dep + '" type="text/css">\n';
|
||||||
|
} else if(ext == 'js') {
|
||||||
|
properties.head += ' <script src="' + dep + '"></script>\n';
|
||||||
|
} else {
|
||||||
|
properties.module = '="' + dep + '"';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
element.text(templateMerge(html, properties));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
directive.ngSetHtml = ['getEmbededTemplate', function(getEmbededTemplate) {
|
||||||
|
return {
|
||||||
|
restrict: 'CA',
|
||||||
|
priority: 10,
|
||||||
|
compile: function(element, attr) {
|
||||||
|
element.html(getEmbededTemplate(attr.ngSetHtml));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
directive.ngEvalJavascript = ['getEmbededTemplate', function(getEmbededTemplate) {
|
||||||
|
return {
|
||||||
|
compile: function (element, attr) {
|
||||||
|
var script = getEmbededTemplate(attr.ngEvalJavascript);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (window.execScript) { // IE
|
||||||
|
window.execScript(script || '""'); // IE complains when evaling empty string
|
||||||
|
} else {
|
||||||
|
window.eval(script);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (window.console) {
|
||||||
|
window.console.log(script, '\n', e);
|
||||||
|
} else {
|
||||||
|
window.alert(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location', function($templateCache, $browser, docsRootScope, $location) {
|
||||||
|
return {
|
||||||
|
terminal: true,
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
var modules = [];
|
||||||
|
|
||||||
|
modules.push(['$provide', function($provide) {
|
||||||
|
$provide.value('$templateCache', $templateCache);
|
||||||
|
$provide.value('$anchorScroll', angular.noop);
|
||||||
|
$provide.value('$browser', $browser);
|
||||||
|
$provide.provider('$location', function() {
|
||||||
|
this.$get = function() { return $location; };
|
||||||
|
this.html5Mode = angular.noop;
|
||||||
|
});
|
||||||
|
$provide.decorator('$defer', ['$rootScope', '$delegate', function($rootScope, $delegate) {
|
||||||
|
return angular.extend(function(fn, delay) {
|
||||||
|
if (delay && delay > 50) {
|
||||||
|
return setTimeout(function() {
|
||||||
|
$rootScope.$apply(fn);
|
||||||
|
}, delay);
|
||||||
|
} else {
|
||||||
|
return $delegate.apply(this, arguments);
|
||||||
|
}
|
||||||
|
}, $delegate);
|
||||||
|
}]);
|
||||||
|
$provide.decorator('$rootScope', ['$delegate', function(embedRootScope) {
|
||||||
|
docsRootScope.$watch(function() {
|
||||||
|
embedRootScope.$digest();
|
||||||
|
});
|
||||||
|
return embedRootScope;
|
||||||
|
}]);
|
||||||
|
}]);
|
||||||
|
if (attrs.ngEmbedApp) modules.push(attrs.ngEmbedApp);
|
||||||
|
|
||||||
|
element.bind('click', function(event) {
|
||||||
|
if (event.target.attributes.getNamedItem('ng-click')) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
angular.bootstrap(element, modules);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
service.reindentCode = function() {
|
||||||
|
return function (text, spaces) {
|
||||||
|
if (!text) return text;
|
||||||
|
var lines = text.split(/\r?\n/);
|
||||||
|
var prefix = ' '.substr(0, spaces || 0);
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// remove any leading blank lines
|
||||||
|
while (lines.length && lines[0].match(/^\s*$/)) lines.shift();
|
||||||
|
// remove any trailing blank lines
|
||||||
|
while (lines.length && lines[lines.length - 1].match(/^\s*$/)) lines.pop();
|
||||||
|
var minIndent = 999;
|
||||||
|
for (i = 0; i < lines.length; i++) {
|
||||||
|
var line = lines[0];
|
||||||
|
var reindentCode = line.match(/^\s*/)[0];
|
||||||
|
if (reindentCode !== line && reindentCode.length < minIndent) {
|
||||||
|
minIndent = reindentCode.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; i++) {
|
||||||
|
lines[i] = prefix + lines[i].substring(minIndent);
|
||||||
|
}
|
||||||
|
lines.push('');
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
service.templateMerge = ['reindentCode', function(indentCode) {
|
||||||
|
return function(template, properties) {
|
||||||
|
return template.replace(/\{\{(\w+)(?:\:(\d+))?\}\}/g, function(_, key, indent) {
|
||||||
|
var value = properties[key];
|
||||||
|
|
||||||
|
if (indent) {
|
||||||
|
value = indentCode(value, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value == undefined ? '' : value;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
service.getEmbededTemplate = ['reindentCode', function(reindentCode) {
|
||||||
|
return function (id) {
|
||||||
|
return reindentCode(angular.element(document.getElementById(id)).html(), 0);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
angular.module('bootstrapPrettify', []).directive(directive).factory(service);
|
||||||
158
src/bootstrap/bootstrap.js
vendored
Normal file
158
src/bootstrap/bootstrap.js
vendored
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var directive = {};
|
||||||
|
|
||||||
|
directive.dropdownToggle =
|
||||||
|
['$document', '$location', '$window',
|
||||||
|
function ($document, $location, $window) {
|
||||||
|
var openElement = null, close;
|
||||||
|
return {
|
||||||
|
restrict: 'C',
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
scope.$watch(function(){return $location.path();}, function() {
|
||||||
|
close && close();
|
||||||
|
});
|
||||||
|
|
||||||
|
element.parent().bind('click', function(event) {
|
||||||
|
close && close();
|
||||||
|
});
|
||||||
|
|
||||||
|
element.bind('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
|
var iWasOpen = false;
|
||||||
|
|
||||||
|
if (openElement) {
|
||||||
|
iWasOpen = openElement === element;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iWasOpen){
|
||||||
|
element.parent().addClass('open');
|
||||||
|
openElement = element;
|
||||||
|
|
||||||
|
close = function (event) {
|
||||||
|
event && event.preventDefault();
|
||||||
|
event && event.stopImmediatePropagation();
|
||||||
|
$document.unbind('click', close);
|
||||||
|
element.parent().removeClass('open');
|
||||||
|
close = null;
|
||||||
|
openElement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$document.bind('click', close);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
directive.tabbable = function() {
|
||||||
|
return {
|
||||||
|
restrict: 'C',
|
||||||
|
compile: function(element) {
|
||||||
|
var navTabs = angular.element('<ul class="nav nav-tabs"></ul>'),
|
||||||
|
tabContent = angular.element('<div class="tab-content"></div>');
|
||||||
|
|
||||||
|
tabContent.append(element.contents());
|
||||||
|
element.append(navTabs).append(tabContent);
|
||||||
|
},
|
||||||
|
controller: ['$scope', '$element', function($scope, $element) {
|
||||||
|
var navTabs = $element.contents().eq(0),
|
||||||
|
ngModel = $element.controller('ngModel') || {},
|
||||||
|
tabs = [],
|
||||||
|
selectedTab;
|
||||||
|
|
||||||
|
ngModel.$render = function() {
|
||||||
|
var $viewValue = this.$viewValue;
|
||||||
|
|
||||||
|
if (selectedTab ? (selectedTab.value != $viewValue) : $viewValue) {
|
||||||
|
if(selectedTab) {
|
||||||
|
selectedTab.paneElement.removeClass('active');
|
||||||
|
selectedTab.tabElement.removeClass('active');
|
||||||
|
selectedTab = null;
|
||||||
|
}
|
||||||
|
if($viewValue) {
|
||||||
|
for(var i = 0, ii = tabs.length; i < ii; i++) {
|
||||||
|
if ($viewValue == tabs[i].value) {
|
||||||
|
selectedTab = tabs[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedTab) {
|
||||||
|
selectedTab.paneElement.addClass('active');
|
||||||
|
selectedTab.tabElement.addClass('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addPane = function(element, attr) {
|
||||||
|
var li = angular.element('<li><a href></a></li>'),
|
||||||
|
a = li.find('a'),
|
||||||
|
tab = {
|
||||||
|
paneElement: element,
|
||||||
|
paneAttrs: attr,
|
||||||
|
tabElement: li
|
||||||
|
};
|
||||||
|
|
||||||
|
tabs.push(tab);
|
||||||
|
|
||||||
|
attr.$observe('value', update)();
|
||||||
|
attr.$observe('title', function(){ update(); a.text(tab.title); })();
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
tab.title = attr.title;
|
||||||
|
tab.value = attr.value || attr.title;
|
||||||
|
if (!ngModel.$setViewValue && (!ngModel.$viewValue || tab == selectedTab)) {
|
||||||
|
// we are not part of angular
|
||||||
|
ngModel.$viewValue = tab.value;
|
||||||
|
}
|
||||||
|
ngModel.$render();
|
||||||
|
}
|
||||||
|
|
||||||
|
navTabs.append(li);
|
||||||
|
li.bind('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (ngModel.$setViewValue) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
ngModel.$setViewValue(tab.value);
|
||||||
|
ngModel.$render();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// we are not part of angular
|
||||||
|
ngModel.$viewValue = tab.value;
|
||||||
|
ngModel.$render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
tab.tabElement.remove();
|
||||||
|
for(var i = 0, ii = tabs.length; i < ii; i++ ) {
|
||||||
|
if (tab == tabs[i]) {
|
||||||
|
tabs.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
directive.tabPane = function() {
|
||||||
|
return {
|
||||||
|
require: '^tabbable',
|
||||||
|
restrict: 'C',
|
||||||
|
link: function(scope, element, attrs, tabsCtrl) {
|
||||||
|
element.bind('$remove', tabsCtrl.addPane(element, attrs));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
angular.module('bootstrap', []).directive(directive);
|
||||||
3990
src/bootstrap/css/bootstrap.css
vendored
Normal file
3990
src/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
30
src/bootstrap/google-prettify/prettify.css
Normal file
30
src/bootstrap/google-prettify/prettify.css
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
.com { color: #93a1a1; }
|
||||||
|
.lit { color: #195f91; }
|
||||||
|
.pun, .opn, .clo { color: #93a1a1; }
|
||||||
|
.fun { color: #dc322f; }
|
||||||
|
.str, .atv { color: #D14; }
|
||||||
|
.kwd, .linenums .tag { color: #1e347b; }
|
||||||
|
.typ, .atn, .dec, .var { color: teal; }
|
||||||
|
.pln { color: #48484c; }
|
||||||
|
|
||||||
|
.prettyprint {
|
||||||
|
padding: 8px;
|
||||||
|
background-color: #f7f7f9;
|
||||||
|
border: 1px solid #e1e1e8;
|
||||||
|
}
|
||||||
|
.prettyprint.linenums {
|
||||||
|
-webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
|
||||||
|
-moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
|
||||||
|
box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Specify class=linenums on a pre to get line numbering */
|
||||||
|
ol.linenums {
|
||||||
|
margin: 0 0 0 33px; /* IE indents via margin-left */
|
||||||
|
}
|
||||||
|
ol.linenums li {
|
||||||
|
padding-left: 12px;
|
||||||
|
color: #bebec5;
|
||||||
|
line-height: 18px;
|
||||||
|
text-shadow: 0 1px 0 #fff;
|
||||||
|
}
|
||||||
1536
src/bootstrap/google-prettify/prettify.js
Normal file
1536
src/bootstrap/google-prettify/prettify.js
Normal file
File diff suppressed because it is too large
Load diff
157
test/bootstrap/bootstrapSpec.js
vendored
Normal file
157
test/bootstrap/bootstrapSpec.js
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('bootstrap', function() {
|
||||||
|
var $compile, $rootScope, element;
|
||||||
|
|
||||||
|
function clickTab(element, index) {
|
||||||
|
browserTrigger(element.children().eq(0).children().eq(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(module('bootstrap'));
|
||||||
|
beforeEach(inject(function(_$compile_, _$rootScope_) {
|
||||||
|
$compile = _$compile_;
|
||||||
|
$rootScope = _$rootScope_;
|
||||||
|
}));
|
||||||
|
beforeEach(function(){
|
||||||
|
function findTab(element, index) {
|
||||||
|
return _jQuery(element[0]).find('> .nav-tabs > li').eq(index);
|
||||||
|
}
|
||||||
|
function findTabPane(element, index) {
|
||||||
|
return _jQuery(element[0]).find('> .tab-content > .tab-pane').eq(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addMatchers({
|
||||||
|
toHaveTab: function(index, title) {
|
||||||
|
var tab = findTab(element, index);
|
||||||
|
|
||||||
|
this.message = function() {
|
||||||
|
if (tab.length) {
|
||||||
|
return 'Expect tab index ' + index + ' to be ' + toJson(title) + ' but was ' + toJson(tab.text());
|
||||||
|
} else {
|
||||||
|
return 'Expect tab index ' + index + ' to be ' + toJson(title) + ' but there are only ' +
|
||||||
|
element.children().length + ' tabs.';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return tab.length && tab.text() == title;
|
||||||
|
},
|
||||||
|
|
||||||
|
toHaveTabPane: function(index, title) {
|
||||||
|
var tabPane = findTabPane(element, index);
|
||||||
|
|
||||||
|
this.message = function() {
|
||||||
|
if (tabPane.length) {
|
||||||
|
return 'Expect tab pane index ' + index + ' to be ' + toJson(title) + ' but was ' + toJson(tabPane.text());
|
||||||
|
} else {
|
||||||
|
return 'Expect tab pane index ' + index + ' to be ' + toJson(title) + ' but there are only ' +
|
||||||
|
element.children().length + 'tab panes.';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return tabPane.length && tabPane.text() == title;
|
||||||
|
},
|
||||||
|
|
||||||
|
toHaveSelected: function(index) {
|
||||||
|
var tab = findTab(element, index);
|
||||||
|
var tabPane = findTabPane(element, index);
|
||||||
|
|
||||||
|
this.message = function() {
|
||||||
|
return 'Expect tab index ' + index + ' to be selected\n' +
|
||||||
|
' TAB: ' + angular.mock.dump(tab) + '\n' +
|
||||||
|
'TAB-PANE: ' + angular.mock.dump(tabPane);
|
||||||
|
};
|
||||||
|
|
||||||
|
return tabPane.hasClass('active') && tab.hasClass('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
dealoc(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('tabbable', function() {
|
||||||
|
|
||||||
|
it('should create the right structure', function() {
|
||||||
|
element = $compile(
|
||||||
|
'<div class="tabbable">' +
|
||||||
|
'<div class="tab-pane" title="first">tab1</div>' +
|
||||||
|
'<div class="tab-pane" title="second">tab2</div>' +
|
||||||
|
'</div>')($rootScope);
|
||||||
|
|
||||||
|
$rootScope.$apply();
|
||||||
|
|
||||||
|
expect(element).toHaveTab(0, 'first');
|
||||||
|
expect(element).toHaveTab(1, 'second');
|
||||||
|
|
||||||
|
expect(element).toHaveTabPane(0, 'tab1');
|
||||||
|
expect(element).toHaveTabPane(1, 'tab2');
|
||||||
|
|
||||||
|
expect(element).toHaveSelected(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should respond to tab click', function(){
|
||||||
|
element = $compile(
|
||||||
|
'<div class="tabbable">' +
|
||||||
|
'<div class="tab-pane" title="first">tab1</div>' +
|
||||||
|
'<div class="tab-pane" title="second">tab2</div>' +
|
||||||
|
'</div>')($rootScope);
|
||||||
|
|
||||||
|
expect(element).toHaveSelected(0);
|
||||||
|
clickTab(element, 1);
|
||||||
|
expect(element).toHaveSelected(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should select the first tab in repeater', function() {
|
||||||
|
element = $compile(
|
||||||
|
'<div class="tabbable">' +
|
||||||
|
'<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value="tab-{{id}}">' +
|
||||||
|
'Tab content {{id}}!' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>')($rootScope);
|
||||||
|
$rootScope.$apply();
|
||||||
|
|
||||||
|
expect(element).toHaveSelected(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('ngModel', function() {
|
||||||
|
it('should bind to model', function() {
|
||||||
|
$rootScope.tab = 'B';
|
||||||
|
|
||||||
|
element = $compile(
|
||||||
|
'<div class="tabbable" ng-model="tab">' +
|
||||||
|
'<div class="tab-pane" title="first" value="A">tab1</div>' +
|
||||||
|
'<div class="tab-pane" title="second" value="B">tab2</div>' +
|
||||||
|
'</div>')($rootScope);
|
||||||
|
|
||||||
|
$rootScope.$apply();
|
||||||
|
expect(element).toHaveSelected(1);
|
||||||
|
|
||||||
|
$rootScope.tab = 'A';
|
||||||
|
$rootScope.$apply();
|
||||||
|
expect(element).toHaveSelected(0);
|
||||||
|
|
||||||
|
clickTab(element, 1);
|
||||||
|
expect($rootScope.tab).toEqual('B');
|
||||||
|
expect(element).toHaveSelected(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should not overwrite the model', function() {
|
||||||
|
$rootScope.tab = 'tab-2';
|
||||||
|
element = $compile(
|
||||||
|
'<div class="tabbable" ng-model="tab">' +
|
||||||
|
'<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value="tab-{{id}}">' +
|
||||||
|
'Tab content {{id}}!' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>')($rootScope);
|
||||||
|
$rootScope.$apply();
|
||||||
|
|
||||||
|
expect(element).toHaveSelected(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
91
test/bootstrap/code.html
Normal file
91
test/bootstrap/code.html
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="../../src/angular-bootstrap.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$script('src/bootstrap/google-prettify/prettify', 'prettify');
|
||||||
|
$script.ready('angular', function() {
|
||||||
|
$script(['src/bootstrap/bootstrap-prettify', 'src/bootstrap/bootstrap'], 'myCode');
|
||||||
|
angular.module('myApp', []).run(function($rootScope){ $rootScope.text = 'WORKS!' });
|
||||||
|
});
|
||||||
|
$script.ready(['myCode', 'prettify'], function() {
|
||||||
|
angular.bootstrap(document, ['bootstrapPrettify', 'bootstrap']);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="../../src/bootstrap/google-prettify/prettify.css" type="text/css">
|
||||||
|
<link rel="stylesheet" href="../../src/bootstrap/css/bootstrap.css" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="span12">
|
||||||
|
<h1>AngularJS is {{'working'}}</h1>
|
||||||
|
|
||||||
|
<h2>Directive: <code>prettify</code></h2>
|
||||||
|
<pre class="prettyprint linenums">
|
||||||
|
<p>Sample text here...</p>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Directive: <code>ng-set-text</code></h2>
|
||||||
|
<pre class="prettyprint linenums" ng-set-text="hello.html"></pre>
|
||||||
|
<script type="text/html" id="hello.html">
|
||||||
|
<h1>Hello World!</h1>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h2>Directive: <code>ng-html-wrap</code></h2>
|
||||||
|
<pre class="prettyprint linenums" ng-set-text="hello.html" ng-html-wrap="angular.js angular-resource.js myApp abc.js abc.css"></pre>
|
||||||
|
|
||||||
|
<h2>Directive <code>ng-embed-app</code></h2>
|
||||||
|
<div ng-embed-app="myApp">{{text}}</div>
|
||||||
|
|
||||||
|
<h1>Bootstrap</h1>
|
||||||
|
|
||||||
|
<h2>Directive <code>drop-down-toggle</code></h2>
|
||||||
|
<div class="btn btn-primary dropdown">
|
||||||
|
<a href="#ABC" class="dropdown-toggle">
|
||||||
|
Account
|
||||||
|
<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>One</li>
|
||||||
|
<li>Two</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 ng-init="state = 'tab-2' ">Directive <code>tabbable</code></h2>
|
||||||
|
state = {{state}}
|
||||||
|
|
||||||
|
<div class="tabbable" ng-model="state">
|
||||||
|
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
|
||||||
|
Tab content {{id}}!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div class="tabbable" ng-model="state">
|
||||||
|
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
|
||||||
|
Tab content {{id}}!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div class="tabbable">
|
||||||
|
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
|
||||||
|
Tab content {{id}}!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in a new issue