Better example widget

- syntax highlighting
- tabless design
- rename widget to doc:example
- rename widget files (wiki_widget.* -> doc_widget.*)
- example section is now optional
This commit is contained in:
Igor Minar 2010-11-05 21:12:37 -07:00
parent effcd340e9
commit 324694a58b
15 changed files with 189 additions and 161 deletions

View file

@ -42,8 +42,8 @@ var work = callback.chain(function () {
copy('docs-scenario.html', callback.chain());
copy('index.html', callback.chain());
mergeTemplate('docs.js', 'docs.js', documentation, callback.chain());
mergeTemplate('wiki_widgets.css', 'wiki_widgets.css', documentation, callback.chain());
mergeTemplate('wiki_widgets.js', 'wiki_widgets.js', documentation, callback.chain());
mergeTemplate('doc_widgets.css', 'doc_widgets.css', documentation, callback.chain());
mergeTemplate('doc_widgets.js', 'doc_widgets.js', documentation, callback.chain());
console.log('DONE');
});
if (!this.testmode) work();

36
docs/doc_widgets.css Normal file
View file

@ -0,0 +1,36 @@
@namespace doc url("http://docs.angularjs.org/");
doc\:example {
display: none;
}
ul.doc-example {
list-style-type: none;
position: relative;
width: 700px;
font-size: 14px;
}
ul.doc-example > li {
border: 2px solid gray;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
background-color: white;
margin-bottom: 20px;
}
ul.doc-example > li.doc-example-heading {
border: none;
border-radius: none;
margin-bottom: -10px;
}
li.doc-example-live {
padding: 10px;
font-size: 1.2em;
}
div.syntaxhighlighter {
padding-bottom: 1px !important; /* fix to remove unnecessary scrollbars http://is.gd/gSMgC */
}

49
docs/doc_widgets.js Normal file
View file

@ -0,0 +1,49 @@
(function(){
var HTML_TEMPLATE =
'<!DOCTYPE HTML>\n' +
'<html xmlns:ng="http://angularjs.org">\n' +
' <head>\n' +
' <title>Angular Example</title>\n' +
' <script type="text/javascript"\n' +
' src="../angular.js" ng:autobind></script>\n' +
' </head>\n' +
' <body>\n' +
'_HTML_SOURCE_\n' +
' </body>\n' +
'</html>';
angular.widget('doc:example', function(element){
this.descend(true); //compile the example code
element.hide();
var example = element.find('doc\\:source').eq(0),
exampleSrc = example.text(),
scenario = element.find('doc\\:scenario').eq(0);
var tabs = angular.element(
'<ul class="doc-example">' +
'<li class="doc-example-heading"><h3>Source</h3></li>' +
'<li class="doc-example-source" ng:non-bindable><pre class="brush: js"></pre></li>' +
'<li class="doc-example-heading"><h3>Live Preview</h3></li>' +
'<li class="doc-example-live">' + exampleSrc +'</li>' +
'<li class="doc-example-heading"><h3>Scenario Test</h3></li>' +
'<li class="doc-example-scenario"><pre class="brush: js">' + scenario.text() + '</pre></li>' +
'</ul>');
tabs.find('li.doc-example-source > pre').text(exampleSrc);
element.html('');
element.append(tabs);
element.show();
var script = (exampleSrc.match(/<script[^\>]*>([\s\S]*)<\/script>/) || [])[1] || '';
try {
eval(script);
} catch (e) {
alert(e);
}
return function() {
SyntaxHighlighter.highlight();
}
});
})();

View file

@ -28,6 +28,15 @@ angular.filter.{{shortName}}({{paramFirst.name}}{{#paramRest}}, {{name}}{{/param
<h3>CSS</h3>
{{{css}}}
<WIKI:SOURCE style="display:block;">
{{{example}}}
</WIKI:SOURCE>
{{#example}}
<h2>Example</h2>
{{{exampleDescription}}}
<doc:example>
<doc:source>
{{/example}}
{{{example}}}
{{#example}}
</doc:source>
<doc:scenario>{{{scenario}}}</doc:scenario>
</doc:example>
{{/example}}

View file

@ -19,6 +19,15 @@ var modelValue = angular.formatter.{{shortName}}.parse(userInputString);
<h3>CSS</h3>
{{{css}}}
<WIKI:SOURCE style="display:block;">
{{{example}}}
</WIKI:SOURCE>
{{#example}}
<h2>Example</h2>
{{{exampleDescription}}}
<doc:example>
<doc:source>
{{/example}}
{{{example}}}
{{#example}}
</doc:source>
<doc:scenario>{{{scenario}}}</doc:scenario>
</doc:example>
{{/example}}

View file

@ -1,12 +1,18 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org" wiki:ng="http://angularjs.org">
<html xmlns:ng="http://angularjs.org/" xmlns:doc="http://docs.angularjs.org/">
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script type="text/javascript" src="docs-data.js"></script>
<script type="text/javascript" src="../angular.min.js" ng:autobind></script>
<script type="text/javascript" src="wiki_widgets.js"></script>
<link rel="stylesheet" href="wiki_widgets.css" type="text/css" media="screen" />
<script type="text/javascript" src="doc_widgets.js"></script>
<link rel="stylesheet" href="doc_widgets.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js"></script>
<link rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" type="text/css" media="screen" />
<link rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" type="text/css" media="screen" />
<script type="text/javascript">
SyntaxHighlighter['defaults'].toolbar = false;
function DocsController() {
this.docs = NG_DOC;
window.$root = this.$root;

View file

@ -1,6 +1,15 @@
<h1><tt>{{name}}</tt></h1>
{{{description}}}
{{#example}}<WIKI:SOURCE style="display:block;">{{/example}}
{{{example}}}
{{#example}}</WIKI:SOURCE>{{/example}}
{{#example}}
<h2>Example</h2>
{{{exampleDescription}}}
<doc:example>
<doc:source>
{{/example}}
{{{example}}}
{{#example}}
</doc:source>
<doc:scenario>{{{scenario}}}</doc:scenario>
</doc:example>
{{/example}}

View file

@ -25,9 +25,15 @@ angular.validator.{{shortName}}({{paramFirst.name}}{{#paramRest}}{{^default}}, {
<h3>CSS</h3>
{{{css}}}
{{#example}}
<h2>Example</h2>
{{{exampleDescription}}}
<WIKI:SOURCE style="display:block;">
{{{example}}}
</WIKI:SOURCE>
<doc:example>
<doc:source>
{{/example}}
{{{example}}}
{{#example}}
</doc:source>
<doc:scenario>{{{scenario}}}</doc:scenario>
</doc:example>
{{/example}}

View file

@ -25,6 +25,15 @@
<h3>CSS</h3>
{{{css}}}
<WIKI:SOURCE style="display:block;">
{{{example}}}
</WIKI:SOURCE>
{{#example}}
<h2>Example</h2>
{{{exampleDescription}}}
<doc:example>
<doc:source>
{{/example}}
{{{example}}}
{{#example}}
</doc:source>
<doc:scenario>{{{scenario}}}</doc:scenario>
</doc:example>
{{/example}}

View file

@ -1,58 +0,0 @@
WIKI\:SOURCE,
WIKI\:SOURCE>ul.tabs,
WIKI\:SOURCE>ul.tabs>li {
display: block;
margin: 0;
padding: 0;
}
WIKI\:SOURCE>ul.tabs {
margin: 0 !important;
padding: 0 !important;
}
WIKI\:SOURCE > ul.tabs > li.tab {
margin: 0 0 0 .8em !important;
display: inline-block;
border: 1px solid gray;
padding: .1em .8em .4em .8em !important;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
border-bottom: none;
cursor: pointer;
background-color: lightgray;
margin-bottom: -2px;
position: relative;
z-index: 0;
}
WIKI\:SOURCE > ul.tabs > li.tab.selected {
z-index: 2;
background-color: white;
font-weight: bold;
border-width: 2px;
}
WIKI\:SOURCE > ul.tabs > li.pane {
border: 2px solid gray;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
background-color: white;
padding: 5px !important;
}
WIKI\:SOURCE > ul.tabs > li.pane {
display:none;
}
WIKI\:SOURCE > ul.tabs > li.pane.selected {
position: relative;
z-index: 1;
display:block;
}
WIKI\:SOURCE > ul.tabs > li.pane.source {
font-size: .8em !important;
}
//////////////////

View file

@ -1,51 +0,0 @@
(function(){
var HTML_TEMPLATE =
'<!DOCTYPE HTML>\n' +
'<html xmlns:ng="http://angularjs.org">\n' +
' <head>\n' +
' <script type="text/javascript"\n' +
' src="http://angularjs.org/ng/js/angular-debug.js" ng:autobind></script>\n' +
' </head>\n' +
' <body>\n' +
'_HTML_SOURCE_\n' +
' </body>\n' +
'</html>';
angular.widget('WIKI:SOURCE', function(element){
this.descend(true);
var html = element.text();
element.show();
var tabs = angular.element(
'<ul class="tabs">' +
'<li class="tab selected" to="angular">&lt;angular/&gt;</li>' +
'<li class="tab" to="plain">plain</li>' +
'<li class="tab" to="source">source</li>' +
'<li class="pane selected angular example">' + html + '</li>' +
'<li class="pane plain" ng:non-bindable>' + html + '</li>' +
'<li class="pane source" ng:non-bindable><pre class="brush: js; html-script: true"></pre></li>' +
'</ul>');
var pre = tabs.
find('>li.source>pre').
text(HTML_TEMPLATE.replace('_HTML_SOURCE_', html));
var color = element.attr('color') || 'white';
element.html('');
element.append(tabs);
element.find('>ul.tabs>li.pane').css('background-color', color);
var script = (html.match(/<script[^\>]*>([\s\S]*)<\/script>/) || [])[1] || '';
try {
eval(script);
} catch (e) {
alert(e);
}
return function(element){
element.find('>ul.tabs>li.tab').click(function(){
if ($(this).is(".selected")) return;
element.
find('>ul.tabs>li.selected').
add(this).
add(element.find('>ul>li.pane.' + angular.element(this).attr('to'))).
toggleClass('selected');
});
};
});
})();

View file

@ -165,9 +165,11 @@ var _undefined = undefined,
* # Syntax
* Attach a validator on user input widgets using the `ng:validate` attribute.
*
* <WIKI:SOURCE>
* <doc:example>
* <doc:source>
* Change me: &lt;input type="text" name="number" ng:validate="integer" value="123"&gt;
* </WIKI:SOURCE>
* </doc:source>
* </doc:example>
*
* # Writing your own Validators
* Writing your own validator is easy. To make a function available as a
@ -255,6 +257,11 @@ var _undefined = undefined,
* the DOM in addition to transforming the input.
*
*
* @exampleDescription
* The following example filter reverses a text string. In addition, it conditionally makes the
* text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM
* modification).
*
* @example
<script type="text/javascript">
angular.filter('reverse', function(input, uppercase, color) {
@ -271,11 +278,6 @@ var _undefined = undefined,
return out;
});
</script>
The following example filter reverses a text string. In addition, it conditionally makes the
text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM
modification).
<hr/>
<span ng:non-bindable="true">{{"hello"|reverse}}</span>: {{"hello"|reverse}}<br>
<span ng:non-bindable="true">{{"hello"|reverse:true}}</span>: {{"hello"|reverse:true}}<br>
<span ng:non-bindable="true">{{"hello"|reverse:true:"blue"}}</span>:
@ -340,20 +342,22 @@ var _undefined = undefined,
* }
* });
* </script>
*
* Formatted: <input type="text" name="data" value="&lt;angular/&gt;" ng:format="reverse"/><br/>
* Stored: <input type="text" name="data"/><br/>
* <pre>{{data}}</pre>
*
*
* @scenario
* it('should store reverse', function(){
* expect(element('.example :input:first').val()).toEqual('<angular/>');
* expect(element('.example :input:last').val()).toEqual('>/RALUGNA<');
* expect(element('.doc-example input:first').val()).toEqual('<angular/>');
* expect(element('.doc-example input:last').val()).toEqual('>/RALUGNA<');
*
* this.addFutureAction('change to XYZ', function($window, $document, done){
* $document.elements('.example :input:last').val('XYZ').trigger('change');
* $document.elements('.doc-example input:last').val('XYZ').trigger('change');
* done();
* });
* expect(element('.example :input:first').val()).toEqual('zyx');
* expect(element('input:first').val()).toEqual('zyx');
* });
*/
angularFormatter = extensionMap(angular, 'formatter'),

View file

@ -103,7 +103,7 @@ angularFormatter.number = formatter(toString, function(obj){
* it('should format lists', function(){
* expect(binding('value')).toEqual('value=["chair","table"]');
* this.addFutureAction('change to XYZ', function($window, $document, done){
* $document.elements('.example :input:last').val(',,a,b,').trigger('change');
* $document.elements('.doc-example :input:last').val(',,a,b,').trigger('change');
* done();
* });
* expect(binding('value')).toEqual('value=["a","b"]');
@ -140,7 +140,7 @@ angularFormatter.list = formatter(
* it('should format trim', function(){
* expect(binding('value')).toEqual('value="book"');
* this.addFutureAction('change to XYZ', function($window, $document, done){
* $document.elements('.example :input:last').val(' text ').trigger('change');
* $document.elements('.doc-example :input:last').val(' text ').trigger('change');
* done();
* });
* expect(binding('value')).toEqual('value="text"');

View file

@ -17,7 +17,7 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate non ssn', function(){
* var textBox = element('.example :input');
* var textBox = element('.doc-example :input');
* expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
* expect(textBox.val()).toEqual('123-45-6789');
*
@ -54,17 +54,17 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate number', function(){
* var n1 = element('.example :input[name=n1]');
* var n1 = element('.doc-example :input[name=n1]');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('n1').enter('1.x');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
*
* var n2 = element('.example :input[name=n2]');
* var n2 = element('.doc-example :input[name=n2]');
* expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
* input('n2').enter('9');
* expect(n2.attr('className')).toMatch(/ng-validation-error/);
*
* var n3 = element('.example :input[name=n3]');
* var n3 = element('.doc-example :input[name=n3]');
* expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
* input('n3').enter('201');
* expect(n3.attr('className')).toMatch(/ng-validation-error/);
@ -106,17 +106,17 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate integer', function(){
* var n1 = element('.example :input[name=n1]');
* var n1 = element('.doc-example :input[name=n1]');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('n1').enter('1.1');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
*
* var n2 = element('.example :input[name=n2]');
* var n2 = element('.doc-example :input[name=n2]');
* expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
* input('n2').enter('10.1');
* expect(n2.attr('className')).toMatch(/ng-validation-error/);
*
* var n3 = element('.example :input[name=n3]');
* var n3 = element('.doc-example :input[name=n3]');
* expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
* input('n3').enter('100.1');
* expect(n3.attr('className')).toMatch(/ng-validation-error/);
@ -148,7 +148,7 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate date', function(){
* var n1 = element('.example :input');
* var n1 = element('.doc-example :input');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('text').enter('123/123/123');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
@ -180,7 +180,7 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate email', function(){
* var n1 = element('.example :input');
* var n1 = element('.doc-example :input');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('text').enter('a@b.c');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
@ -209,7 +209,7 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate phone', function(){
* var n1 = element('.example :input');
* var n1 = element('.doc-example :input');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('text').enter('+12345678');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
@ -241,7 +241,7 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate url', function(){
* var n1 = element('.example :input');
* var n1 = element('.doc-example :input');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('text').enter('abc://server/path');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
@ -271,7 +271,7 @@ extend(angularValidator, {
*
* @scenario
* it('should invalidate json', function(){
* var n1 = element('.example :input');
* var n1 = element('.doc-example :input');
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
* input('json').enter('{name}');
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
@ -344,7 +344,7 @@ extend(angularValidator, {
*
* @scenario
* it('should change color in delayed way', function(){
* var textBox = element('.example :input');
* var textBox = element('.doc-example :input');
* expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
* expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
*

View file

@ -398,15 +398,15 @@ angularWidget('option', function(){
*
* @scenario
* it('should load date filter', function(){
* expect(element('.example ng\\:include').text()).toMatch(/angular\.filter\.date/);
* expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/);
* });
* it('should change to hmtl filter', function(){
* select('url').option('angular.filter.html.html');
* expect(element('.example ng\\:include').text()).toMatch(/angular\.filter\.html/);
* expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/);
* });
* it('should change to blank', function(){
* select('url').option('(blank)');
* expect(element('.example ng\\:include').text()).toEqual('');
* expect(element('.doc-example ng\\:include').text()).toEqual('');
* });
*/
angularWidget('ng:include', function(element){
@ -489,11 +489,11 @@ angularWidget('ng:include', function(element){
*
* @scenario
* it('should start in settings', function(){
* expect(element('.example ng\\:switch').text()).toEqual('Settings Div');
* expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div');
* });
* it('should change to home', function(){
* select('switch').option('home');
* expect(element('.example ng\\:switch').text()).toEqual('Home Span');
* expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span');
* });
*/
var ngSwitch = angularWidget('ng:switch', function (element){