initial commit

This commit is contained in:
John Bintz 2014-02-18 22:31:50 -05:00
commit 11348f2c42
7 changed files with 552 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
bower_components/
node_modules/

18
Gruntfile.coffee Normal file
View File

@ -0,0 +1,18 @@
module.exports = (grunt) ->
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks)
grunt.initConfig {
coffee:
compile:
expand: true
cwd: 'src'
src: [ '*.coffee' ]
dest: 'dist'
ext: '.js'
watch:
coffee:
files: [ 'src/*.coffee' ]
tasks: [ 'coffee:compile' ]
}
grunt.registerTask 'default', 'watch:coffee'

1
README.md Normal file
View File

@ -0,0 +1 @@
John's AngularJS-based presentation system.

18
bower.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "angular-presentation",
"version": "0.0.0",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "~2.1.0",
"angular": "~1.2.14-build.2273",
"js-beautify": "~1.4.2",
"solarized": "~0.1.2",
"angular-ui-utils": "bower-keypress"
}
}

292
dist/angular-presentation.js vendored Normal file
View File

@ -0,0 +1,292 @@
(function() {
var codeGrabber, presentation, processCodeBlock;
presentation = angular.module('presentation', ['ui.keypress']);
presentation.factory('boundScopeHelper', function() {
return function(directive) {
var originalCompile, originalLink;
originalCompile = directive.compile;
originalLink = directive.link;
directive.compile = function(tE, tA, transclude) {
var key, value, _ref;
_ref = directive.scope;
for (key in _ref) {
value = _ref[key];
tA[key] = key;
}
if (originalCompile != null) {
return originalCompile(tE, tA, transclude);
} else if (originalLink) {
return originalLink;
} else {
return function(scope, element, attrs) {};
}
};
delete directive.link;
return directive;
};
});
presentation.factory('presentationOptions', function() {
var Options;
Options = (function() {
function Options() {}
Options.prototype.slides = [];
Options.prototype.currentSlide = null;
Options.prototype.addSlide = function(id) {
this.slides.push(id);
return this.currentSlide || (this.currentSlide = id);
};
Options.prototype.currentSlideIndex = function() {
return this.slides.indexOf(this.currentSlide);
};
Options.prototype.nextSlide = function() {
var index;
index = this.currentSlideIndex() + 1;
if (index < this.slides.length) {
return this.switchToSlide(index);
}
};
Options.prototype.previousSlide = function() {
var index;
index = this.currentSlideIndex() - 1;
if (index > -1) {
return this.switchToSlide(index);
}
};
Options.prototype.switchToSlide = function(index) {
return this.currentSlide = this.slides[index];
};
Options.prototype.hasPrevious = function() {
return this.currentSlideIndex() > 0;
};
Options.prototype.hasNext = function() {
return this.currentSlideIndex() < this.slides.length - 1;
};
Options.prototype.nextID = function() {
return "slide-" + this.slides.length;
};
return Options;
})();
return new Options();
});
presentation.directive('presentation', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
templateUrl: 'presentation.html',
controller: function($scope, presentationOptions) {
return $scope.options = presentationOptions;
}
};
});
presentation.directive('slide', function(boundScopeHelper) {
return boundScopeHelper({
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'slide.html',
scope: {
'options': '='
},
compile: function(tE, tA, transclude) {
var id;
id = tA.id;
return function(scope, element, attrs) {
scope.id = id || scope.options.nextID();
scope.options.addSlide(scope.id);
scope.state || (scope.state = {});
return scope.codeBlocks || (scope.codeBlocks = {});
};
}
});
});
presentation.simpleDirective = function(name, options) {
if (options == null) {
options = {};
}
return this.directive(name, function($sce) {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: true,
templateUrl: name + '.html',
compile: function(tE, tA, transclude) {
return function(scope, element, attrs) {
return transclude(scope, function(clone, innerScope) {
clone = angular.element('<div />').append(clone);
if (options.postLink != null) {
options.postLink(scope, name, clone);
return scope[name] = $sce.trustAsHtml(scope[name]);
}
});
};
}
};
});
};
presentation.simpleDirective('title', {
postLink: function(scope, name, clone) {
return scope[name] = clone.text();
}
});
presentation.simpleDirective('subtitle', {
postLink: function(scope, name, clone) {
return scope[name] = clone.html();
}
});
presentation.directive('controls', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'controls.html'
};
});
codeGrabber = function(scope, element, name) {
var html;
html = element.html();
scope.codeBlocks || (scope.codeBlocks = {});
return scope.codeBlocks[name] = html;
};
presentation.directive('script', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
if (attrs.type === 'text/code-grabber') {
return codeGrabber(scope, element, attrs["for"]);
}
}
};
});
presentation.directive('codeGrabber', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
return codeGrabber(scope, element, attrs.codeGrabber);
}
};
});
presentation.directive('codeRunner', function($compile) {
return {
restrict: 'E',
replace: true,
link: function(scope, element, attrs) {
var target;
element.after("<div class='code-runner' />");
target = element.next();
element.remove();
return scope.$watch('codeBlocks', function(codeBlocks) {
var content;
content = angular.element("<div />").append(codeBlocks[attrs["for"]]);
$compile(content)(scope);
target.html('');
return target.append(content);
}, true);
}
};
});
processCodeBlock = function(code, language, callback) {
var beautifier, length, line, lines, output, prismLanguage;
prismLanguage = null;
beautifier = (function() {
switch (language) {
case 'html':
prismLanguage = 'markup';
return window.html_beautify;
case 'javascript':
case 'json':
prismLanguage = 'javascript';
return window.js_beautify;
case 'css':
case 'scss':
case 'sass':
prismLanguage = 'css';
return window.css_beautify;
default:
prismLanguage = language;
return function(code, options) {
return code;
};
}
})();
output = beautifier(code, {
indent_size: 2
}).replace(/</g, "&lt;");
lines = output.split("\n");
length = lines[0].length - lines[0].replace(/^ */, '').length;
output = ((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = lines.length; _i < _len; _i++) {
line = lines[_i];
_results.push(line.substr(length));
}
return _results;
})()).join("\n");
return callback(Prism.highlight(output, Prism.languages[prismLanguage]));
};
presentation.directive('codeDisplayer', function(boundScopeHelper) {
return boundScopeHelper({
restrict: 'E',
replace: true,
scope: {
codeBlocks: '=',
state: '='
},
templateUrl: 'code_displayer.html',
link: function(scope, element, attrs) {
return scope.$watch('codeBlocks', function(codeBlocks) {
if (codeBlocks && codeBlocks[attrs["for"]]) {
return processCodeBlock(codeBlocks[attrs["for"]], attrs.language, function(highlightedCode) {
return element.find('code').append(highlightedCode);
});
}
}, true);
}
});
});
presentation.directive('pre', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
if (attrs.language != null) {
return processCodeBlock(element.text(), attrs.language, function(highlightedCode) {
console.log(highlightedCode);
element.html('');
element.append('<code />');
return element.find('code').append(highlightedCode);
});
}
}
};
});
}).call(this);

17
package.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "angular-presentation",
"version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "BSD",
"devDependencies": {
"grunt": "~0.4.2",
"matchdep": "~0.3.0",
"grunt-contrib-coffee": "~0.10.0",
"grunt-contrib-watch": "~0.5.3"
}
}

View File

@ -0,0 +1,203 @@
presentation = angular.module 'presentation', [ 'ui.keypress' ]
presentation.factory 'boundScopeHelper', ->
(directive) ->
originalCompile = directive.compile
originalLink = directive.link
directive.compile = (tE, tA, transclude) ->
tA[key] = key for key, value of directive.scope
if originalCompile?
originalCompile(tE, tA, transclude)
else if originalLink
originalLink
else
(scope, element, attrs) ->
delete directive.link
directive
presentation.factory 'presentationOptions', ->
class Options
slides: []
currentSlide: null
addSlide: (id) ->
@slides.push(id)
@currentSlide ||= id
currentSlideIndex: -> @slides.indexOf(@currentSlide)
nextSlide: ->
index = @currentSlideIndex() + 1
if index < @slides.length
@switchToSlide(index)
previousSlide: ->
index = @currentSlideIndex() - 1
if index > -1
@switchToSlide(index)
switchToSlide: (index) ->
@currentSlide = @slides[index]
hasPrevious: ->
@currentSlideIndex() > 0
hasNext: ->
@currentSlideIndex() < @slides.length - 1
nextID: ->
"slide-#{@slides.length}"
new Options()
presentation.directive 'presentation', ->
restrict: 'E'
transclude: true
replace: true
templateUrl: 'presentation.html'
controller: ($scope, presentationOptions) ->
$scope.options = presentationOptions
presentation.directive 'slide', (boundScopeHelper) ->
boundScopeHelper(
restrict: 'E'
replace: true
transclude: true
templateUrl: 'slide.html'
scope:
'options': '='
compile: (tE, tA, transclude) ->
id = tA.id
(scope, element, attrs) ->
scope.id = id || scope.options.nextID()
scope.options.addSlide(scope.id)
scope.state ||= {}
scope.codeBlocks ||= {}
)
presentation.simpleDirective = (name, options = {}) ->
@directive name, ($sce) ->
restrict: 'E'
replace: true
transclude: true
scope: true
templateUrl: name + '.html'
compile: (tE, tA, transclude) ->
(scope, element, attrs) ->
transclude scope, (clone, innerScope) ->
clone = angular.element('<div />').append(clone)
if options.postLink?
options.postLink(scope, name, clone)
scope[name] = $sce.trustAsHtml(scope[name])
presentation.simpleDirective 'title',
postLink: (scope, name, clone) ->
scope[name] = clone.text()
presentation.simpleDirective 'subtitle',
postLink: (scope, name, clone) ->
scope[name] = clone.html()
presentation.directive 'controls', ->
restrict: 'E'
replace: true
templateUrl: 'controls.html'
codeGrabber = (scope, element, name) ->
html = element.html()
scope.codeBlocks ||= {}
scope.codeBlocks[name] = html
presentation.directive 'script', ->
restrict: 'E'
link: (scope, element, attrs) ->
if attrs.type == 'text/code-grabber'
codeGrabber scope, element, attrs.for
presentation.directive 'codeGrabber', ->
restrict: 'A'
link: (scope, element, attrs) ->
codeGrabber scope, element, attrs.codeGrabber
presentation.directive 'codeRunner', ($compile) ->
restrict: 'E'
replace: true
link: (scope, element, attrs) ->
element.after "<div class='code-runner' />"
target = element.next()
element.remove()
scope.$watch(
'codeBlocks',
(codeBlocks) ->
content = angular.element("<div />").append(codeBlocks[attrs.for])
$compile(content)(scope)
target.html('')
target.append(content)
, true
)
processCodeBlock = (code, language, callback) ->
prismLanguage = null
beautifier = switch language
when 'html'
prismLanguage = 'markup'
window.html_beautify
when 'javascript', 'json'
prismLanguage = 'javascript'
window.js_beautify
when 'css', 'scss', 'sass'
prismLanguage = 'css'
window.css_beautify
else
prismLanguage = language
(code, options) -> code
output = beautifier(code, { indent_size: 2 }).replace(/</g, "&lt;")
lines = output.split("\n")
length = lines[0].length - lines[0].replace(/^ */, '').length
output = (line.substr(length) for line in lines).join("\n")
callback(Prism.highlight(output, Prism.languages[prismLanguage]))
presentation.directive 'codeDisplayer', (boundScopeHelper) ->
boundScopeHelper {
restrict: 'E'
replace: true
scope: {
codeBlocks: '='
state: '='
}
templateUrl: 'code_displayer.html'
link: (scope, element, attrs) ->
scope.$watch(
'codeBlocks', (codeBlocks) ->
if codeBlocks && codeBlocks[attrs.for]
processCodeBlock codeBlocks[attrs.for], attrs.language, (highlightedCode) ->
element.find('code').append(highlightedCode)
, true)
}
presentation.directive 'pre', ->
restrict: 'E'
link: (scope, element, attrs) ->
if attrs.language?
processCodeBlock element.text(), attrs.language, (highlightedCode) ->
console.log highlightedCode
element.html('')
element.append('<code />')
element.find('code').append(highlightedCode)