diff --git a/css/stylesheet.css b/css/stylesheet.css new file mode 100644 index 0000000..1343d90 --- /dev/null +++ b/css/stylesheet.css @@ -0,0 +1,112 @@ +header, footer { + padding: 20px; + background-image: url('../img/header.png'); + background-size: 256px 256px; +} +footer { + color: #fff; + text-align: center; +} +.nyt-logo { + max-height: 40px; + margin-top: 5px; + margin-right: 5px; +} + +nav.navbar { + margin-bottom: 10px; + background-color: #fff; + border: 0px; + border-radius: 2px; +} +#navbar { + margin: 0px; +} +#navbar .navbar-nav li iframe { + margin-top: 15px; +} +#navbar .navbar-nav li:last-child iframe { + margin-right: 15px; +} + +@media screen and (max-width: 767px) { + #navbar .navbar-nav li iframe { + display: none; + } +} + +.mast-head { + margin: 10px 0; +} +.mast-head h1 { + margin-bottom: 15px; + color: #fff; +} +.mast-head p { + color: #fff; +} + +.mast-links { + padding-top: 10px; +} + +.mast-links > * { + vertical-align: middle; + margin-bottom: 10px; +} + +.mast-links > .btn { + margin-right: 30px; +} +main { + margin: 10px 20px; +} +main .container { + margin-bottom: 40px; +} + +code.hljs { + border: 1px solid #ccc; + padding: 1em; + white-space: pre; + margin-bottom: 10px; +} + +.example { + position: relative; + border: 1px solid #ccc; + padding: 1em 1em 0.5em 1em; + border-radius: 4px 4px 0 0; +} + +.example:after { + content: "Example"; + position: absolute; + top: 0px; + right: 0px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + background-color: #f5f5f5; + border: 1px solid #ccc; + color: #9da0a4; + border-radius: 0px 4px 0px 4px; + border-width: 0px 0px 1px 1px; +} + +.example + code.hljs { + border-top: 0; + border-radius: 0px 0px 4px 4px; +} + +.example > * { + margin-bottom: 10px; +} + +.example > div.toggle { + margin-right: 10px; +} + +.table-striped code { + background-color: inherit; +} \ No newline at end of file diff --git a/dist/angular-bootstrap-toggle.css b/dist/angular-bootstrap-toggle.css index 7e485aa..c66e3b4 100644 --- a/dist/angular-bootstrap-toggle.css +++ b/dist/angular-bootstrap-toggle.css @@ -4,7 +4,6 @@ margin-right: 5px; } .toggle { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; position: relative; overflow: hidden; } @@ -51,46 +50,27 @@ width: 0px; border-width: 0 1px; } -.toggle.btn { - min-width: 59px; - min-height: 34px; +.toggle-on-pad.btn.btn-lg { + padding-right: 32px; } -.toggle-on.btn { +.toggle-off-pad.btn.btn-lg { + padding-left: 32px; +} +.toggle-on-pad.btn { padding-right: 24px; } -.toggle-off.btn { +.toggle-off-pad.btn { padding-left: 24px; } -.toggle.btn-lg { - min-width: 79px; - min-height: 45px; -} -.toggle-on.btn-lg { - padding-right: 31px; -} -.toggle-off.btn-lg { - padding-left: 31px; -} -.toggle-handle.btn-lg { - width: 40px; -} -.toggle.btn-sm { - min-width: 50px; - min-height: 30px; -} -.toggle-on.btn-sm { +.toggle-on-pad.btn.btn-sm { padding-right: 20px; } -.toggle-off.btn-sm { +.toggle-off-pad.btn.btn-sm { padding-left: 20px; } -.toggle.btn-xs { - min-width: 35px; - min-height: 22px; -} -.toggle-on.btn-xs { - padding-right: 12px; +.toggle-on-pad.btn.btn-xs { + padding-right: 9px; } -.toggle-off.btn-xs { - padding-left: 12px; +.toggle-off-pad.btn.btn-xs { + padding-left: 9px; } diff --git a/dist/angular-bootstrap-toggle.js b/dist/angular-bootstrap-toggle.js index 37f492a..b5ea46e 100644 --- a/dist/angular-bootstrap-toggle.js +++ b/dist/angular-bootstrap-toggle.js @@ -62,6 +62,13 @@ * Example: */ toggleStyle: '', + /** + * Type: string + * Default: '' + * Description: Passes a class to the toggle's first immediate child + **/ + toggleClass: '', + style: '', /** * Type: string * Default: '' @@ -89,8 +96,8 @@ }) .controller('ToggleController', - ['$scope', '$attrs', '$interpolate', '$log', 'toggleConfig', '$toggleSuppressError', - function ($scope, $attrs, $interpolate, $log, toggleConfig, $toggleSuppressError) { + ['$scope', '$attrs', '$interpolate', '$log', '$document', 'toggleConfig', '$toggleSuppressError', + function ($scope, $attrs, $interpolate, $log, $document, toggleConfig, $toggleSuppressError) { var self = this; var labels, spans, divs; var ngModelCtrl; @@ -122,6 +129,18 @@ if (self.offstyle) { self.offClass = self.offstyle; } + // Special treatment for style, now deprecated and replaced with toggleClass + if (self.style) { + self.toggleClass = self.style; + } + + // Special case: empty on and off labels (replace with blank space) + if (self.on === '') { + self.on = ' '; + } + if (self.off === '') { + self.off = ' '; + } this.init = function (ngModelCtrl_) { ngModelCtrl = ngModelCtrl_; @@ -139,6 +158,40 @@ angular.element(self.onElement).html(self.on); angular.element(self.offElement).html(self.off); + // Set the button size + angular.element(self.wrapperElement).addClass(self.size); + angular.element(self.onElement).addClass(self.size); + angular.element(self.offElement).addClass(self.size); + angular.element(self.handleElement).addClass(self.size); + + // Set the toggleClass on the wrapper + angular.element(self.wrapperElement).addClass(self.toggleClass); + + // Calculate the propery width + if (!self.width) { + var wrapperComputedWidth = Math.max( + self.onElement.scrollWidth, + self.offElement.scrollWidth + ) + Math.max(self.handleElement.scrollWidth, 16) / 2 + 2; + self.width = wrapperComputedWidth + 'px'; + } + + // Calculate the proper height + if (!self.height) { + var wrapperComputedHeight = Math.max( + self.onElement.scrollHeight, + self.offElement.scrollHeight) + 2; + self.height = wrapperComputedHeight + 'px'; + } + + // Add the toggle-on and toggle-off classes, that change position and size of the labels + // and make sure that the buttons are properly placed. + // Once this is done, the height and width properties of the labels is no longer relevant, + // because of their new placement. + angular.element(self.onElement).addClass(self.onClass).addClass('toggle-on'); + angular.element(self.offElement).addClass(self.offClass).addClass('toggle-off'); + + // Compute first style self.computeStyle(); ngModelCtrl.$render = function () { @@ -165,38 +218,9 @@ // Build an object for widget's ng-style $scope.wrapperStyle = (self.toggleStyle) ? $scope.$parent.$eval(self.toggleStyle) : {}; + $scope.wrapperStyle.width = self.width; + $scope.wrapperStyle.height = self.height; - // Calculate the proper width - if (self.width) { - $scope.wrapperStyle.width = self.width; - } else { - var wrapperComputedWidth = Math.max( - self.onElement.scrollWidth, - self.offElement.scrollWidth) + 12; - $scope.wrapperStyle.width = wrapperComputedWidth + 'px'; - } - - // Calculate the proper height - if (self.height) { - $scope.wrapperStyle.height = self.height; - } else { - var wrapperComputedHeight = Math.max( - self.onElement.offsetHeight, - self.offElement.offsetHeight); - var wrapperHeight = self.wrapperElement.offsetHeight; - - if (wrapperHeight < wrapperComputedHeight && - self.size !== 'btn-xs' && self.size !== 'btn-sm') { - $scope.wrapperStyle.height = wrapperComputedHeight + 'px'; - } else { - $scope.wrapperStyle.height = wrapperHeight + 'px'; - } - } - - // Build arrays that will be passed to widget's ng-class. - $scope.onComputedClass = [self.onClass , self.size, 'toggle-on']; - $scope.offComputedClass = [self.offClass, self.size, 'toggle-off']; - $scope.handleComputedClass = [self.size , 'toggle-handle']; }; this.toggle = function () { @@ -229,6 +253,7 @@ } }); }); + }]) .directive('toggle', function () { @@ -237,9 +262,9 @@ template: '
' + '
' + - '' + - '' + - '' + + '' + + '' + + '' + '
' + '
', scope: { diff --git a/dist/angular-bootstrap-toggle.min.css b/dist/angular-bootstrap-toggle.min.css index 7e2622c..17c6dc9 100644 --- a/dist/angular-bootstrap-toggle.min.css +++ b/dist/angular-bootstrap-toggle.min.css @@ -1 +1 @@ -.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}.toggle{font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;position:relative;overflow:hidden}.toggle-group,.toggle-off,.toggle-on{position:absolute;top:0;bottom:0}.toggle-group{width:200%;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}.toggle.off .toggle-group{left:-100%}.toggle-on{left:0;right:50%;margin:0;border:0;border-radius:0}.toggle-off{left:50%;right:0;margin:0;border:0;border-radius:0}.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}.toggle.btn{min-width:59px;min-height:34px}.toggle-on.btn{padding-right:24px}.toggle-off.btn{padding-left:24px}.toggle.btn-lg{min-width:79px;min-height:45px}.toggle-on.btn-lg{padding-right:31px}.toggle-off.btn-lg{padding-left:31px}.toggle-handle.btn-lg{width:40px}.toggle.btn-sm{min-width:50px;min-height:30px}.toggle-on.btn-sm{padding-right:20px}.toggle-off.btn-sm{padding-left:20px}.toggle.btn-xs{min-width:35px;min-height:22px}.toggle-on.btn-xs{padding-right:12px}.toggle-off.btn-xs{padding-left:12px} \ No newline at end of file +.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}.toggle{position:relative;overflow:hidden}.toggle-group,.toggle-off,.toggle-on{position:absolute;top:0;bottom:0}.toggle-group{width:200%;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}.toggle.off .toggle-group{left:-100%}.toggle-on{left:0;right:50%;margin:0;border:0;border-radius:0}.toggle-off{left:50%;right:0;margin:0;border:0;border-radius:0}.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}.toggle-on-pad.btn.btn-lg{padding-right:32px}.toggle-off-pad.btn.btn-lg{padding-left:32px}.toggle-on-pad.btn{padding-right:24px}.toggle-off-pad.btn{padding-left:24px}.toggle-on-pad.btn.btn-sm{padding-right:20px}.toggle-off-pad.btn.btn-sm{padding-left:20px}.toggle-on-pad.btn.btn-xs{padding-right:9px}.toggle-off-pad.btn.btn-xs{padding-left:9px} \ No newline at end of file diff --git a/dist/angular-bootstrap-toggle.min.js b/dist/angular-bootstrap-toggle.min.js index dba21da..c207077 100644 --- a/dist/angular-bootstrap-toggle.min.js +++ b/dist/angular-bootstrap-toggle.min.js @@ -1 +1 @@ -!function(){"use strict";angular.module("ui.toggle",[]).value("$toggleSuppressError",!1).constant("toggleConfig",{btnCheckboxFalse:!1,btnCheckboxTrue:!0,on:"On",off:"Off",size:"",onClass:"btn-primary",onstyle:"",offClass:"btn-default",offstyle:"",toggleStyle:"",width:"",height:"",disabled:!1}).controller("ToggleController",["$scope","$attrs","$interpolate","$log","toggleConfig","$toggleSuppressError",function(e,t,l,n,a,o){var s,r=this,i=Object.keys(a);angular.forEach(i,function(n,o){if(angular.isDefined(t[n]))switch(typeof a[n]){case"string":r[n]=l(t[n])(e.$parent);break;case"function":break;default:r[n]=e.$parent.$eval(t[n])}else r[n]=a[n]}),r.onstyle&&(r.onClass=r.onstyle),r.offstyle&&(r.offClass=r.offstyle),this.init=function(l){s=l;var n=r.element.find("label"),a=r.element.find("span"),o=r.element.find("div");r.wrapperElement=o[0],r.onElement=n[0],r.offElement=n[1],r.handleElement=a[0],angular.element(r.onElement).html(r.on),angular.element(r.offElement).html(r.off),r.computeStyle(),s.$render=function(){r.toggle()},angular.isDefined(t.ngChange)&&s.$viewChangeListeners.push(function(){e.$eval(t.ngChange)})},this.computeStyle=function(){if(angular.element(r.onElement).attr("disabled",r.disabled),angular.element(r.offElement).attr("disabled",r.disabled),angular.element(r.handleElement).attr("disabled",r.disabled),e.wrapperStyle=r.toggleStyle?e.$parent.$eval(r.toggleStyle):{},r.width)e.wrapperStyle.width=r.width;else{var t=Math.max(r.onElement.scrollWidth,r.offElement.scrollWidth)+12;e.wrapperStyle.width=t+"px"}if(r.height)e.wrapperStyle.height=r.height;else{var l=Math.max(r.onElement.offsetHeight,r.offElement.offsetHeight),n=r.wrapperElement.offsetHeight;n
',scope:{ngModel:"="},require:["toggle","ngModel"],controller:"ToggleController",controllerAs:"toggle",compile:function(e,t,l){return{post:function(e,t,l,n){var a=n[0],o=n[1];a.element=t,a.init(o)},pre:function(){}}}}})}(); \ No newline at end of file +!function(){"use strict";angular.module("ui.toggle",[]).value("$toggleSuppressError",!1).constant("toggleConfig",{btnCheckboxFalse:!1,btnCheckboxTrue:!0,on:"On",off:"Off",size:"",onClass:"btn-primary",onstyle:"",offClass:"btn-default",offstyle:"",toggleStyle:"",toggleClass:"",style:"",width:"",height:"",disabled:!1}).controller("ToggleController",["$scope","$attrs","$interpolate","$log","$document","toggleConfig","$toggleSuppressError",function(e,l,t,n,a,o,s){var r,g=this,i=Object.keys(o);angular.forEach(i,function(n,a){if(angular.isDefined(l[n]))switch(typeof o[n]){case"string":g[n]=t(l[n])(e.$parent);break;case"function":break;default:g[n]=e.$parent.$eval(l[n])}else g[n]=o[n]}),g.onstyle&&(g.onClass=g.onstyle),g.offstyle&&(g.offClass=g.offstyle),g.style&&(g.toggleClass=g.style),""===g.on&&(g.on=" "),""===g.off&&(g.off=" "),this.init=function(t){r=t;var n=g.element.find("label"),a=g.element.find("span"),o=g.element.find("div");if(g.wrapperElement=o[0],g.onElement=n[0],g.offElement=n[1],g.handleElement=a[0],angular.element(g.onElement).html(g.on),angular.element(g.offElement).html(g.off),angular.element(g.wrapperElement).addClass(g.size),angular.element(g.onElement).addClass(g.size),angular.element(g.offElement).addClass(g.size),angular.element(g.handleElement).addClass(g.size),angular.element(g.wrapperElement).addClass(g.toggleClass),!g.width){var s=Math.max(g.onElement.scrollWidth,g.offElement.scrollWidth)+Math.max(g.handleElement.scrollWidth,16)/2+2;g.width=s+"px"}if(!g.height){var i=Math.max(g.onElement.scrollHeight,g.offElement.scrollHeight)+2;g.height=i+"px"}angular.element(g.onElement).addClass(g.onClass).addClass("toggle-on"),angular.element(g.offElement).addClass(g.offClass).addClass("toggle-off"),g.computeStyle(),r.$render=function(){g.toggle()},angular.isDefined(l.ngChange)&&r.$viewChangeListeners.push(function(){e.$eval(l.ngChange)})},this.computeStyle=function(){angular.element(g.onElement).attr("disabled",g.disabled),angular.element(g.offElement).attr("disabled",g.disabled),angular.element(g.handleElement).attr("disabled",g.disabled),e.wrapperStyle=g.toggleStyle?e.$parent.$eval(g.toggleStyle):{},e.wrapperStyle.width=g.width,e.wrapperStyle.height=g.height},this.toggle=function(){r.$viewValue?angular.element(g.wrapperElement).removeClass("off "+g.offClass).addClass(g.onClass):angular.element(g.wrapperElement).addClass("off "+g.offClass).removeClass(g.onClass)},e.onSwitch=function(e){return!g.disabled&&(r.$setViewValue(!r.$viewValue),r.$render(),!0)},angular.forEach(i,function(e,t){l.$observe(e,function(l){g[e]!==l&&(g[e]=l,g.computeStyle())})})}]).directive("toggle",function(){return{restrict:"E",template:'
',scope:{ngModel:"="},require:["toggle","ngModel"],controller:"ToggleController",controllerAs:"toggle",compile:function(e,l,t){return{post:function(e,l,t,n){var a=n[0],o=n[1];a.element=l,a.init(o)},pre:function(){}}}}})}(); \ No newline at end of file diff --git a/img/header.png b/img/header.png new file mode 100644 index 0000000..eb8d58b Binary files /dev/null and b/img/header.png differ diff --git a/img/nyt.png b/img/nyt.png new file mode 100644 index 0000000..4025f26 Binary files /dev/null and b/img/nyt.png differ diff --git a/img/nytdev.svg b/img/nytdev.svg new file mode 100644 index 0000000..b529b34 --- /dev/null +++ b/img/nytdev.svg @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..0b4f25e --- /dev/null +++ b/index.html @@ -0,0 +1,366 @@ + + + + + + + + + + + Angular Bootstrap Toggle + + + + + + + + +
+ +
+
+

Angular Bootstrap Toggle

+ +

AngularJS version of + Bootstrap Toggle

+ + +
+
+
+ +
+
+
+

Getting Started

+
+

Dependencies

+ +

+ This repository contains a set of native AngularJS directives based on + Bootstrap's markup and CSS. As a result no dependency on jQuery or Bootstrap's + JavaScript is required. The only required dependencies are: +

+
    +
  • AngularJS (requires AngularJS 1.3.x, + tested with 1.7.4). +
  • +
  • Bootstrap CSS (tested with version + 3.3.7). +
  • +
+

Installation

+ +

You can download + the latest + version of Angular Bootstrap Toggle or use CDN to load the library.

+ + <link + href="https://gitcdn.github.io/angular-bootstrap-toggle/{version}/dist/angular-bootstrap-toggle.min.css" + rel="stylesheet"> + <script + src="https://gitcdn.github.io/bootstrap-toggle/{version}/dist/angular-bootstrap-toggle.min.js"></script> + +

Bower Installation

+
$ bower install angular-bootstrap-toggle --save
+

As soon as you've got all the files downloaded and included in your page you just need to declare + a dependency on the ui.toggle module:
+

+
angular.module('myModule', ['ui.toggle']);
+
+
+
+

Usage

+
+ +

Basic example

+ +

value: {{toggleValue}}

+ +

change event triggered times: {{clickTimes}}

+ +
+ +
+ +

Options

+ +

Options can be passed via attributes

+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDefaultDescription
onstring | html"On"Text of the on toggle
offstring | html"Off"Text of the off toggle
sizestring"btn" + Size class of the toggle. Possible values + are:btn-lg,btn,btn-sm,btn-xs
+ Refer to Bootstrap Button + Sizes documentation for more information. +
on-classstring"btn-primary" + Class of the on toggle.
Possible values + are:btn-default,btn-primary,btn-success,btn-info,btn-warning,btn-danger
+ Refer to Bootstrap Button + Options documentation for more information. +
off-classstring"btn-default" + Class of the off toggle.
Possible values + are:btn-default,btn-primary,btn-success,btn-info,btn-warning,btn-danger
+ Refer to Bootstrap Button + Options documentation for more information. +
toggle-classstring'' + Appends the value to the class attribute of the toggle. This can be used to apply custom styles. + Refer to Custom Styles for reference. +
+
+
+ +
+

Demos

+
+ +

Sizes

+ +

Bootstrap toggle is available in different sizes. Refer to Bootstrap Button Sizes documentation for + more information.

+ +
+ + + + +
+ +

Colors

+ +

Bootstrap Toggle supports various colors. Refer to Bootstrap Button Options documentation for + more information.

+ +
+ + + + + + +
+ +

Colors Mix

+ +

You can style on state as well as the off state.

+ +
+ + +
+ +

Custom Style

+ +

Customized styles can be applied as easily.

+ +
+ + + + +
+ +

Custom Text

+ +

The text can be changed easily with attributes or options.

+ +
+ +
+ +

Icons/Html Text

+ +

You can easily add icons or images since html is supported for on/off text.

+ +
+ +
+ +

Multiple Lines of Text

+ +

Toggles with multiple lines will adjust its heights.

+ +
+ +
+ +

Animation Speed

+ +

Transition speed can be easily controlled with css transition property on + .toggle-group. You can also turn animation off completely.

+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..2808c2c --- /dev/null +++ b/js/app.js @@ -0,0 +1,66 @@ +/* global FastClick, smoothScroll */ +angular.module('ui.toggle.demo', ['ui.toggle', 'ngTouch', 'ngAnimate', 'ngSanitize'], function ($httpProvider) { + FastClick.attach(document.body); + delete $httpProvider.defaults.headers.common['X-Requested-With']; +}).run(['$location', function ($location) { + //Allows us to navigate to the correct element on initialization + if ($location.path() !== '' && $location.path() !== '/') { + smoothScroll(document.getElementById($location.path().substring(1)), 500, function (el) { + location.replace('#' + el.id); + }); + } +}]) + .controller('MainCtrl', function MainCtrl($scope) { + $scope.clickTimes = 0; + $scope.toggleValue = true; + $scope.changed = function(evt) { + $scope.clickTimes+=1; + }; + }); + +/* + * The following compatibility check is from: + * + * Bootstrap Customizer (http://getbootstrap.com/customize/) + * Copyright 2011-2014 Twitter, Inc. + * + * Licensed under the Creative Commons Attribution 3.0 Unported License. For + * details, see http://creativecommons.org/licenses/by/3.0/. + */ +var isOldBrowser; +(function () { + + var supportsFile = (window.File && window.FileReader && window.FileList && window.Blob); + + function failback() { + isOldBrowser = true; + } + + /** + * Based on: + * Blob Feature Check v1.1.0 + * https://github.com/ssorallen/blob-feature-check/ + * License: Public domain (http://unlicense.org) + */ + var url = window.URL; + var svg = new Blob( + [''], + {type: 'image/svg+xml;charset=utf-8'} + ); + var objectUrl = url.createObjectURL(svg); + + if (/^blob:/.exec(objectUrl) === null || !supportsFile) { + // `URL.createObjectURL` created a URL that started with something other + // than "blob:", which means it has been polyfilled and is not supported by + // this browser. + failback(); + } else { + angular.element('') + .on('load', function () { + isOldBrowser = false; + }) + .on('error', failback) + .attr('src', objectUrl); + } + +})(); \ No newline at end of file diff --git a/js/script.js b/js/script.js new file mode 100644 index 0000000..863728a --- /dev/null +++ b/js/script.js @@ -0,0 +1,49 @@ ++function ($) { + 'use strict'; + + $('.example:not(.skip)').each(function() { + // fetch & encode html + var html = $('
').text($(this).html()).html() + // find number of space/tabs on first line (minus line break) + var count = html.match(/^(\s+)/)[0].length - 1 + // replace tabs/spaces on each lines with + var regex = new RegExp('\\n\\s{'+count+'}', 'g') + var code = html.replace(regex, '\n').replace(/\t/g, ' ').trim() + // other cleanup + code = code.replace(/=""/g,'') + // add code block to dom + $(this).after( $('').html(code) ) + }); + + $('code.highlight').each(function() { + hljs.highlightBlock(this) + }); + +}(jQuery); + +var Demo = function () {} + +Demo.prototype.init = function(selector) { + $(selector).bootstrapToggle(selector) +} +Demo.prototype.destroy = function(selector) { + $(selector).bootstrapToggle('destroy') +} +Demo.prototype.on = function(selector) { + $(selector).bootstrapToggle('on') +} +Demo.prototype.off = function(selector) { + $(selector).bootstrapToggle('off') +} +Demo.prototype.toggle = function(selector) { + $(selector).bootstrapToggle('toggle') +} +Demo.prototype.enable = function(selector) { + $(selector).bootstrapToggle('enable') +} +Demo.prototype.disable = function(selector) { + $(selector).bootstrapToggle('disable') +} + + +demo = new Demo() diff --git a/js/smoothscroll-angular-custom.js b/js/smoothscroll-angular-custom.js new file mode 100644 index 0000000..e33586f --- /dev/null +++ b/js/smoothscroll-angular-custom.js @@ -0,0 +1,97 @@ +/* + * https://github.com/alicelieutier/smoothScroll/ + * A teeny tiny, standard compliant, smooth scroll script with ease-in-out effect and no jQuery (or any other dependancy, FWIW). + * MIT License + */ +window.smoothScroll = (function(){ +// We do not want this script to be applied in browsers that do not support those +// That means no smoothscroll on IE9 and below. +if(document.querySelectorAll === void 0 || window.pageYOffset === void 0 || history.pushState === void 0) { return; } + +// Get the top position of an element in the document +var getTop = function(element) { + // return value of html.getBoundingClientRect().top ... IE : 0, other browsers : -pageYOffset + if(element.nodeName === 'HTML') return -window.pageYOffset + return element.getBoundingClientRect().top + window.pageYOffset; +} +// ease in out function thanks to: +// http://blog.greweb.fr/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/ +var easeInOutCubic = function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 } + +// calculate the scroll position we should be in +// given the start and end point of the scroll +// the time elapsed from the beginning of the scroll +// and the total duration of the scroll (default 500ms) +var position = function(start, end, elapsed, duration) { + if (elapsed > duration) return end; + return start + (end - start) * easeInOutCubic(elapsed / duration); // <-- you can change the easing funtion there + // return start + (end - start) * (elapsed / duration); // <-- this would give a linear scroll +} + +// we use requestAnimationFrame to be called by the browser before every repaint +// if the first argument is an element then scroll to the top of this element +// if the first argument is numeric then scroll to this location +// if the callback exist, it is called when the scrolling is finished +var smoothScroll = function(el, duration, callback){ + duration = duration || 500; + var start = window.pageYOffset; + + if (typeof el === 'number') { + var end = parseInt(el); + } else { + var end = getTop(el); + } + + var clock = Date.now(); + var requestAnimationFrame = window.requestAnimationFrame || + window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || + function(fn){window.setTimeout(fn, 15);}; + + var step = function(){ + var elapsed = Date.now() - clock; + window.scroll(0, position(start, end, elapsed, duration)); + if (elapsed > duration) { + if (typeof callback === 'function') { + callback(el); + } + } else { + requestAnimationFrame(step); + } + } + step(); +} + +var linkHandler = function(ev) { + ev.preventDefault(); + + if (location.hash !== this.hash) { + //NOTE(@ajoslin): Changed this line to stop $digest errors + //window.history.pushState(null, null, this.hash) + angular.element(document).injector().get('$location').hash(this.hash); + } + // using the history api to solve issue #1 - back doesn't work + // most browser don't update :target when the history api is used: + // THIS IS A BUG FROM THE BROWSERS. + // change the scrolling duration in this call + var targetEl = document.getElementById(this.hash.substring(1)); + if (targetEl) { + smoothScroll(document.getElementById(this.hash.substring(1)), 500, function(el) { + location.replace('#' + el.id) + // this will cause the :target to be activated. + }); + } +} + +// We look for all the internal links in the documents and attach the smoothscroll function +document.addEventListener("DOMContentLoaded", function () { + var internal = document.querySelectorAll('a[href^="#"]'), a; + for(var i=internal.length; a=internal[--i];){ + a.addEventListener("click", linkHandler, false); + } +}); + +// return smoothscroll API +return smoothScroll; + +})(); + diff --git a/src/angular-bootstrap-toggle.js b/src/angular-bootstrap-toggle.js index 37f492a..b5ea46e 100644 --- a/src/angular-bootstrap-toggle.js +++ b/src/angular-bootstrap-toggle.js @@ -62,6 +62,13 @@ * Example: */ toggleStyle: '', + /** + * Type: string + * Default: '' + * Description: Passes a class to the toggle's first immediate child + **/ + toggleClass: '', + style: '', /** * Type: string * Default: '' @@ -89,8 +96,8 @@ }) .controller('ToggleController', - ['$scope', '$attrs', '$interpolate', '$log', 'toggleConfig', '$toggleSuppressError', - function ($scope, $attrs, $interpolate, $log, toggleConfig, $toggleSuppressError) { + ['$scope', '$attrs', '$interpolate', '$log', '$document', 'toggleConfig', '$toggleSuppressError', + function ($scope, $attrs, $interpolate, $log, $document, toggleConfig, $toggleSuppressError) { var self = this; var labels, spans, divs; var ngModelCtrl; @@ -122,6 +129,18 @@ if (self.offstyle) { self.offClass = self.offstyle; } + // Special treatment for style, now deprecated and replaced with toggleClass + if (self.style) { + self.toggleClass = self.style; + } + + // Special case: empty on and off labels (replace with blank space) + if (self.on === '') { + self.on = ' '; + } + if (self.off === '') { + self.off = ' '; + } this.init = function (ngModelCtrl_) { ngModelCtrl = ngModelCtrl_; @@ -139,6 +158,40 @@ angular.element(self.onElement).html(self.on); angular.element(self.offElement).html(self.off); + // Set the button size + angular.element(self.wrapperElement).addClass(self.size); + angular.element(self.onElement).addClass(self.size); + angular.element(self.offElement).addClass(self.size); + angular.element(self.handleElement).addClass(self.size); + + // Set the toggleClass on the wrapper + angular.element(self.wrapperElement).addClass(self.toggleClass); + + // Calculate the propery width + if (!self.width) { + var wrapperComputedWidth = Math.max( + self.onElement.scrollWidth, + self.offElement.scrollWidth + ) + Math.max(self.handleElement.scrollWidth, 16) / 2 + 2; + self.width = wrapperComputedWidth + 'px'; + } + + // Calculate the proper height + if (!self.height) { + var wrapperComputedHeight = Math.max( + self.onElement.scrollHeight, + self.offElement.scrollHeight) + 2; + self.height = wrapperComputedHeight + 'px'; + } + + // Add the toggle-on and toggle-off classes, that change position and size of the labels + // and make sure that the buttons are properly placed. + // Once this is done, the height and width properties of the labels is no longer relevant, + // because of their new placement. + angular.element(self.onElement).addClass(self.onClass).addClass('toggle-on'); + angular.element(self.offElement).addClass(self.offClass).addClass('toggle-off'); + + // Compute first style self.computeStyle(); ngModelCtrl.$render = function () { @@ -165,38 +218,9 @@ // Build an object for widget's ng-style $scope.wrapperStyle = (self.toggleStyle) ? $scope.$parent.$eval(self.toggleStyle) : {}; + $scope.wrapperStyle.width = self.width; + $scope.wrapperStyle.height = self.height; - // Calculate the proper width - if (self.width) { - $scope.wrapperStyle.width = self.width; - } else { - var wrapperComputedWidth = Math.max( - self.onElement.scrollWidth, - self.offElement.scrollWidth) + 12; - $scope.wrapperStyle.width = wrapperComputedWidth + 'px'; - } - - // Calculate the proper height - if (self.height) { - $scope.wrapperStyle.height = self.height; - } else { - var wrapperComputedHeight = Math.max( - self.onElement.offsetHeight, - self.offElement.offsetHeight); - var wrapperHeight = self.wrapperElement.offsetHeight; - - if (wrapperHeight < wrapperComputedHeight && - self.size !== 'btn-xs' && self.size !== 'btn-sm') { - $scope.wrapperStyle.height = wrapperComputedHeight + 'px'; - } else { - $scope.wrapperStyle.height = wrapperHeight + 'px'; - } - } - - // Build arrays that will be passed to widget's ng-class. - $scope.onComputedClass = [self.onClass , self.size, 'toggle-on']; - $scope.offComputedClass = [self.offClass, self.size, 'toggle-off']; - $scope.handleComputedClass = [self.size , 'toggle-handle']; }; this.toggle = function () { @@ -229,6 +253,7 @@ } }); }); + }]) .directive('toggle', function () { @@ -237,9 +262,9 @@ template: '
' + '
' + - '' + - '' + - '' + + '' + + '' + + '' + '
' + '
', scope: { diff --git a/src/angular-bootstrap-toggle.less b/src/angular-bootstrap-toggle.less index efd07f7..68c3374 100644 --- a/src/angular-bootstrap-toggle.less +++ b/src/angular-bootstrap-toggle.less @@ -5,7 +5,6 @@ } .toggle { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; position: relative; overflow: hidden; } @@ -54,19 +53,14 @@ border-width: 0 1px; } -.toggle.btn { min-width: 59px; min-height: 34px; } -.toggle-on.btn { padding-right: 24px; } -.toggle-off.btn { padding-left: 24px; } +.toggle-on-pad.btn.btn-lg { padding-right: 32px; } +.toggle-off-pad.btn.btn-lg { padding-left: 32px; } -.toggle.btn-lg { min-width: 79px; min-height: 45px; } -.toggle-on.btn-lg { padding-right: 31px; } -.toggle-off.btn-lg { padding-left: 31px; } -.toggle-handle.btn-lg { width: 40px; } +.toggle-on-pad.btn { padding-right: 24px; } +.toggle-off-pad.btn { padding-left: 24px; } -.toggle.btn-sm { min-width: 50px; min-height: 30px;} -.toggle-on.btn-sm { padding-right: 20px; } -.toggle-off.btn-sm { padding-left: 20px; } +.toggle-on-pad.btn.btn-sm { padding-right: 20px; } +.toggle-off-pad.btn.btn-sm { padding-left: 20px; } -.toggle.btn-xs { min-width: 35px; min-height: 22px;} -.toggle-on.btn-xs { padding-right: 12px; } -.toggle-off.btn-xs { padding-left: 12px; } +.toggle-on-pad.btn.btn-xs { padding-right: 9px; } +.toggle-off-pad.btn.btn-xs { padding-left: 9px; } diff --git a/test/unit/angularBootstrapToggleSpec.js b/test/unit/angularBootstrapToggleSpec.js index 0cca787..150b1ca 100755 --- a/test/unit/angularBootstrapToggleSpec.js +++ b/test/unit/angularBootstrapToggleSpec.js @@ -34,7 +34,7 @@ describe('', function () { }); it('should have customized label elements', function () { - directiveElem = getCompiledElement('') + directiveElem = getCompiledElement(''); var labelElement = directiveElem.find('label'); expect(labelElement).toBeDefined(); @@ -42,6 +42,15 @@ describe('', function () { expect(angular.element(labelElement[1]).text()).toEqual('Disabled'); }); + it('should have customized classes', function () { + directiveElem = getCompiledElement(''); + var labelElement = directiveElem.find('label'); + + expect(labelElement).toBeDefined(); + expect(angular.element(labelElement[0]).hasClass('btn-danger')).toBe(true); + expect(angular.element(labelElement[1]).hasClass('btn-success')).toBe(true); + }); + it('ngChange should be called', function () { directiveElem = getCompiledElement('') var wrapper = directiveElem.find('div')[0];