├── citrix-tech-group-podio-frontend-client-side ├── images │ ├── api.png │ ├── autodt.png │ ├── citrix.png │ ├── fail.jpg │ ├── finger.png │ ├── podio.png │ ├── rails.jpg │ ├── robot.png │ ├── rocket.png │ ├── sass.png │ ├── team.png │ ├── turtle.jpg │ ├── zeus.png │ ├── W3C_logo.jpg │ ├── backbone.png │ ├── browsers.jpg │ ├── firebug.png │ ├── firefox.png │ ├── sublime.png │ ├── supercar.png │ ├── vodafone.png │ ├── clientside.jpg │ ├── evolution.jpg │ ├── fullstack.jpg │ ├── mvc_podio.png │ ├── mvc_podio1.png │ ├── mvc_podio2.png │ ├── mvc_podio3.png │ └── mvc_backbone.png ├── scripts │ └── md │ │ ├── README.md │ │ ├── slides.md │ │ ├── render.py │ │ └── base.html ├── js │ ├── prettify │ │ ├── lang-go.js │ │ ├── lang-ml.js │ │ ├── lang-vb.js │ │ ├── lang-lua.js │ │ ├── lang-sql.js │ │ ├── lang-tex.js │ │ ├── lang-vhdl.js │ │ ├── lang-wiki.js │ │ ├── lang-apollo.js │ │ ├── lang-scala.js │ │ ├── lang-proto.js │ │ ├── lang-yaml.js │ │ ├── lang-hs.js │ │ ├── prettify.css │ │ ├── lang-lisp.js │ │ ├── lang-css.js │ │ ├── lang-n.js │ │ ├── lang-clj.js │ │ ├── prettify.js │ │ └── lang-xq.js │ ├── slides.js │ ├── polyfills │ │ ├── dataset.min.js │ │ ├── classList.min.js │ │ └── history.min.js │ ├── order.js │ ├── slide-controller.js │ ├── modernizr.custom.45394.js │ ├── require-1.0.8.min.js │ ├── hammer.js │ └── slide-deck.js ├── theme │ ├── css │ │ └── phone.css │ └── scss │ │ ├── phone.scss │ │ └── _base.scss ├── app.yaml ├── serve.sh ├── .gitignore ├── config.rb ├── slide_config.js ├── .idea │ ├── codeStyleSettings.xml │ ├── misc.xml │ ├── projectCodeStyle.xml │ └── workspace.xml ├── NOTES.md └── index.html └── .gitignore /citrix-tech-group-podio-frontend-client-side/images/api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/api.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/autodt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/autodt.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/citrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/citrix.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/fail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/fail.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/finger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/finger.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/podio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/podio.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/rails.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/rails.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/robot.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/rocket.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/sass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/sass.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/team.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/turtle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/turtle.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/zeus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/zeus.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/W3C_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/W3C_logo.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/backbone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/backbone.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/browsers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/browsers.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/firebug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/firebug.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/firefox.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/sublime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/sublime.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/supercar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/supercar.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/vodafone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/vodafone.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/scripts/md/README.md: -------------------------------------------------------------------------------- 1 | Want to use markdown instead? 2 | 3 | `python render.py` can do that for you. 4 | 5 | Dependencies: jinja2, markdown. 6 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/clientside.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/clientside.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/evolution.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/evolution.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/fullstack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/fullstack.jpg -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/mvc_podio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/mvc_podio.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/mvc_podio1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/mvc_podio1.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/mvc_podio2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/mvc_podio2.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/mvc_podio3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/mvc_podio3.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-go.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-go.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-ml.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-ml.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-vb.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-vb.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/images/mvc_backbone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/images/mvc_backbone.png -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-lua.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-lua.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-sql.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-sql.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-tex.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-tex.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-vhdl.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-vhdl.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-wiki.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-wiki.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-apollo.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-apollo.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-scala.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/public-presentations/master/citrix-tech-group-podio-frontend-client-side/js/prettify/lang-scala.js -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/theme/css/phone.css: -------------------------------------------------------------------------------- 1 | slides>slide{-webkit-transition:none !important;-moz-transition:none !important;-webkit-transition:none !important;-o-transition:none !important;transition:none !important} 2 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/slides.js: -------------------------------------------------------------------------------- 1 | require(['order!../slide_config', 'order!modernizr.custom.45394', 2 | 'order!prettify/prettify', 'order!hammer', 'order!slide-controller', 3 | 'order!slide-deck'], function(someModule) { 4 | 5 | }); 6 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-proto.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]); 2 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-yaml.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]); 3 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/app.yaml: -------------------------------------------------------------------------------- 1 | application: my-io-talk 2 | version: 1 3 | runtime: python27 4 | api_version: 1 5 | threadsafe: yes 6 | 7 | handlers: 8 | - url: / 9 | static_files: template.html 10 | upload: template\.html 11 | 12 | - url: /slide_config\.js 13 | static_files: slide_config.js 14 | upload: slide_config\.js 15 | 16 | - url: /js 17 | static_dir: js 18 | 19 | - url: /theme 20 | static_dir: theme 21 | 22 | - url: /images 23 | static_dir: images 24 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/serve.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Starts a basic web server on the port specified. 4 | # 5 | # ./serve.sh 3000 -> http://localhost:3000 6 | # 7 | # Copyright 2012 Eric Bidelman 8 | 9 | port=$1 10 | if [ $# -ne 1 ] 11 | then 12 | port=8000 13 | fi 14 | 15 | if [ $(uname -s) == "Darwin" ] 16 | then 17 | open=open 18 | else 19 | open=xdg-open 20 | fi 21 | 22 | $open http://localhost:$port/template.html && python -m SimpleHTTPServer $port; 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | *.min.css 11 | #*.min.js 12 | .sass-cache/* 13 | 14 | # Packages # 15 | ############ 16 | # it's better to unpack these files and commit the raw source 17 | # git has its own built in compression methods 18 | *.7z 19 | *.dmg 20 | *.gz 21 | *.iso 22 | *.rar 23 | *.tar 24 | *.zip 25 | 26 | # Logs and databases # 27 | ###################### 28 | *.log 29 | *.sql 30 | *.sqlite 31 | 32 | # OS generated files # 33 | ###################### 34 | .DS_Store* 35 | ehthumbs.db 36 | Icon? 37 | Thumbs.db 38 | *~ -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-hs.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n \r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/, 2 | null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]); 3 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | *.min.css 11 | #*.min.js 12 | .sass-cache/* 13 | 14 | # Packages # 15 | ############ 16 | # it's better to unpack these files and commit the raw source 17 | # git has its own built in compression methods 18 | *.7z 19 | *.dmg 20 | *.gz 21 | *.iso 22 | *.rar 23 | *.tar 24 | *.zip 25 | 26 | # Logs and databases # 27 | ###################### 28 | *.log 29 | *.sql 30 | *.sqlite 31 | 32 | # OS generated files # 33 | ###################### 34 | .DS_Store* 35 | ehthumbs.db 36 | Icon? 37 | Thumbs.db 38 | *~ -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/polyfills/dataset.min.js: -------------------------------------------------------------------------------- 1 | (function(){function c(){d=!0;this.removeEventListener("DOMAttrModified",c,!1)}function g(b){return b.replace(h,function(b,a){return a.toUpperCase()})}function e(){var b={};i.call(this.attributes,function(a){if(f=a.name.match(j))b[g(f[1])]=a.value});return b}var i=[].forEach,j=/^data-(.+)/,h=/\-([a-z])/ig,a=document.createElement("div"),d=!1,f;a.dataset==void 0&&(a.addEventListener("DOMAttrModified",c,!1),a.setAttribute("foo","bar"),Element.prototype.__defineGetter__("dataset",d?function(){if(!this._datasetCache)this._datasetCache= 2 | e.call(this);return this._datasetCache}:e),document.addEventListener("DOMAttrModified",function(a){delete a.target._datasetCache},!1))})(); -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-lisp.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a], 3 | ["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]); 4 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | 3 | # Set this to the root of your project when deployed: 4 | http_path = "/" 5 | css_dir = "theme/css" 6 | sass_dir = "theme/scss" 7 | images_dir = "images" 8 | javascripts_dir = "js" 9 | 10 | # You can select your preferred output style here (can be overridden via the command line): 11 | output_style = :compressed #:expanded or :nested or :compact or :compressed 12 | 13 | # To enable relative paths to assets via compass helper functions. Uncomment: 14 | # relative_assets = true 15 | 16 | # To disable debugging comments that display the original location of your selectors. Uncomment: 17 | # line_comments = false 18 | 19 | 20 | # If you prefer the indented syntax, you might want to regenerate this 21 | # project again passing --syntax sass, or you can uncomment this: 22 | # preferred_syntax = :sass 23 | # and then run: 24 | # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass 25 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/theme/scss/phone.scss: -------------------------------------------------------------------------------- 1 | @import "compass/css3/transition"; 2 | 3 | 4 | /*Smartphones (portrait and landscape) ----------- */ 5 | /*@media only screen 6 | and (min-width : 320px) 7 | and (max-width : 480px) { 8 | 9 | }*/ 10 | 11 | /* Smartphones (portrait) ----------- */ 12 | //@media only screen and (max-device-width: 480px) { 13 | /* Styles */ 14 | //$slide-width: 350px; 15 | //$slide-height: 500px; 16 | 17 | slides > slide { 18 | /* width: $slide-width !important; 19 | height: $slide-height !important; 20 | margin-left: -$slide-width / 2 !important; 21 | margin-top: -$slide-height / 2 !important; 22 | */ 23 | // Don't do full slide transitions on mobile. 24 | -webkit-transition: none !important; // Bug in compass? Not sure why the below is not working 25 | @include transition(none !important); 26 | } 27 | 28 | //} 29 | 30 | /* iPhone 4 ----------- */ 31 | @media 32 | only screen and (-webkit-min-device-pixel-ratio : 1.5), 33 | only screen and (min-device-pixel-ratio : 1.5) { 34 | /* Styles */ 35 | } -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/scripts/md/slides.md: -------------------------------------------------------------------------------- 1 | title: Slide Title 2 | class: image 3 | 4 | ![Mobile vs desktop users](image.png) 5 | 6 | --- 7 | 8 | title: Agenda 9 | class: big 10 | 11 | Things we'll cover: 12 | 13 | - Bullet1 14 | - Bullet2 15 | - Bullet3 16 | 17 | --- 18 | 19 | title: Today 20 | class: nobackground fill 21 | 22 | ![Many kinds of devices.](image.png) 23 | 24 | 25 | 26 | --- 27 | 28 | h1: Big Title Slide 29 | class: title-slide 30 | 31 | --- 32 | 33 | title: Code Example 34 | 35 | Media Queries are sweet: 36 | 37 |
38 | @media screen and (max-width: 640px) {
39 |   #sidebar { display: none; }
40 | }
41 | 
42 | 43 | --- 44 | 45 | title: Once more, with JavaScript 46 | 47 |
48 | function isSmall() {
49 |   return window.matchMedia("(min-device-width: ???)").matches;
50 | }
51 | 
52 | function hasTouch() {
53 |   return Modernizr.touch;
54 | }
55 | 
56 | function detectFormFactor() {
57 |   var device = DESKTOP;
58 |   if (hasTouch()) {
59 |     device = isSmall() ? PHONE : TABLET;
60 |   }
61 |   return device;
62 | }
63 | 
64 | 65 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-n.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/, 3 | a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/, 4 | a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]); 5 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/slide_config.js: -------------------------------------------------------------------------------- 1 | var SLIDE_CONFIG = { 2 | // Slide settings 3 | settings: { 4 | title: ' Going client-side on the web', 5 | subtitle: 'Citrix Tech Group', 6 | useBuilds: true, // Default: true. False will turn off slide animation builds. 7 | usePrettify: true, // Default: true 8 | enableSlideAreas: true, // Default: true. False turns off the click areas on either slide of the slides. 9 | enableTouch: true, // Default: true. If touch support should enabled. Note: the device must support touch. 10 | //analytics: 'UA-XXXXXXXX-1', // TODO: Using this breaks GA for some reason (probably requirejs). Update your tracking code in template.html instead. 11 | favIcon: '', 12 | fonts: [ 13 | 'Open Sans:regular,semibold,italic,italicsemibold', 14 | 'Inconsolata' 15 | ] 16 | //theme: ['mytheme'], // Add your own custom themes or styles in /theme/css. Leave off the .css extension. 17 | }, 18 | 19 | // Author information 20 | presenters: [{ 21 | name: 'Kenneth Auchenberg & Daniel Pouzemski', 22 | company: 'Podio', 23 | gplus: '', 24 | twitter: '@auchenberg, @fredsmoo', 25 | www: 'http://kenneth.io, podio.com', 26 | github: '' 27 | }/*, { 28 | name: 'Second Name', 29 | company: 'Job Title, Google', 30 | gplus: 'http://plus.google.com/1234567890', 31 | twitter: '@yourhandle', 32 | www: 'http://www.you.com', 33 | github: 'http://github.com/you' 34 | }*/] 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/order.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS order 1.0.5 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | (function(){function k(a){var b=a.currentTarget||a.srcElement,c;if(a.type==="load"||l.test(b.readyState)){a=b.getAttribute("data-requiremodule");j[a]=!0;for(a=0;c=g[a];a++)if(j[c.name])c.req([c.name],c.onLoad);else break;a>0&&g.splice(0,a);setTimeout(function(){b.parentNode.removeChild(b)},15)}}function m(a){var b,c;a.setAttribute("data-orderloaded","loaded");for(a=0;c=h[a];a++)if((b=i[c])&&b.getAttribute("data-orderloaded")==="loaded")delete i[c],require.addScriptToDom(b);else break;a>0&&h.splice(0, 7 | a)}var f=typeof document!=="undefined"&&typeof window!=="undefined"&&document.createElement("script"),n=f&&(f.async||window.opera&&Object.prototype.toString.call(window.opera)==="[object Opera]"||"MozAppearance"in document.documentElement.style),o=f&&f.readyState==="uninitialized",l=/^(complete|loaded)$/,g=[],j={},i={},h=[],f=null;define({version:"1.0.5",load:function(a,b,c,e){var d;b.nameToUrl?(d=b.nameToUrl(a,null),require.s.skipAsync[d]=!0,n||e.isBuild?b([a],c):o?(e=require.s.contexts._,!e.urlFetched[d]&& 8 | !e.loaded[a]&&(e.urlFetched[d]=!0,require.resourcesReady(!1),e.scriptCount+=1,d=require.attach(d,e,a,null,null,m),i[a]=d,h.push(a)),b([a],c)):b.specified(a)?b([a],c):(g.push({name:a,req:b,onLoad:c}),require.attach(d,null,a,k,"script/cache"))):b([a],c)}})})(); 9 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-clj.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 Google Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | var a=null; 17 | PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a], 18 | ["typ",/^:[\dA-Za-z-]+/]]),["clj"]); 19 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 40 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/polyfills/classList.min.js: -------------------------------------------------------------------------------- 1 | /* @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/ 2 | "use strict";if(typeof document!=="undefined"&&!("classList" in document.createElement("a"))){(function(a){var f="classList",d="prototype",e=(a.HTMLElement||a.Element)[d],g=Object;strTrim=String[d].trim||function(){return this.replace(/^\s+|\s+$/g,"")},arrIndexOf=Array[d].indexOf||function(k){for(var j=0,h=this.length;j 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | Inspections 13 | 14 | 15 | 16 | 17 | CSS 18 | 19 | 20 | 21 | 22 | 23 | 24 | http://www.w3.org/1999/xhtml 25 | 26 | 27 | 28 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/scripts/md/base.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | Google IO 2012 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 |
33 |
34 | 35 | 36 | 37 | 38 |
39 |

40 |

41 |

42 |
43 |
44 | 45 | {% for slide in slides %} 46 | 47 |
48 |

{{ slide.h1 }}

49 |

{{ slide.title }}

50 |
51 |
52 | {{ slide.content }} 53 |
54 |
55 | {% endfor %} 56 | 57 | 58 | 59 |
60 | 61 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/NOTES.md: -------------------------------------------------------------------------------- 1 | Agenda 2 | 3 | # Welcome 4 | -- Who we are 5 | 6 | # Podio 7 | 8 | ## PRINCIPLES 9 | 10 | 1. Constant evolution of product and platform 11 | 1.1 Value for our customers 12 | 1.2 Deliver fast & Fail fast. Try stuff out. Protyping. Then perfect 13 | 2. Data-driven. A/B testing, measurements 14 | 1.1 Smooth transition (from PHP to Rails to JS) 15 | 1.2 Leveraging existing infrastructure (no duplicate code) 16 | 17 | 2. Right tools for the job 18 | 2.1. Avoid complexity 19 | 2.1 KISS 20 | 2.3 Onboard non-JS developers. 21 | 2.4 Built on convensions. 22 | 23 | 3.1 Continuous integration 24 | 3.2 Continuous deployment 25 | 3.3. Feature system 26 | 27 | ## PODIO STACK EVOLUTION 28 | 1. Our prototype (PHP) 29 | 2. Introduction of API. 30 | 3. Project Zeus 31 | 3.2 SASS 32 | # CSS 33 | 1. SASS 34 | 2. Mixins library 35 | 3. OOCSS 36 | 4. CSS reuse -> modules, themes and layouts 37 | 38 | 3.3 Server-sided MVC 39 | 40 | # WHY CLIENT SIDE 41 | 42 | 1. Faster and more responsive UX 43 | 1.1 Our ambition (vision) 44 | - Realtime 45 | 1.2 User expectations (Facebook comparison) 46 | 47 | 2. Leverage the power of clients 48 | 2. Reuse of components 49 | 3. More reliability 50 | 3.1 No state in the DOM (SoC) 51 | 3.2 TestingM 52 | 53 | # WHY BACKBONE 54 | 1. Fit Rails setup. 55 | 2. Live on top. For a long time in parallel 56 | 1. Easy to use 57 | 2. Minimalistic and extensible. 58 | 3. Does not lock you in on patterns. 59 | 4. A lot of movement in the space. (JavaScript MVC, SproutCore, Knockout) 60 | 4. Fits existing infrastructure (RESTful when you need it). 61 | 62 | # BACKBONE 101 (picture?) 63 | 1. Models 64 | 2. Collections 65 | 3. Views 66 | 67 | ## Our learnings towards to the PODIO MVC ARCHITECTURE 68 | Drawbacks of the MV* approach in many JS frameworks: 69 | 1. Tight binding between Views and Models does not scale 70 | 1.2 PodioPicker (store state in memory instead of DOM) 71 | 1.2 Single state can influence multiple components 72 | 1.3 Arregated state from multiple state-models 73 | 1.1 ViewModels vs. StateModels 74 | 75 | 1. Controllers (one or more) 76 | 1.1 Views and Models are not bound 77 | 1.2 Single point of responsibility (top-down actions only) 78 | 1.3 Context-awareness (specific vs. generic) 79 | 1.4 Component management and global state 80 | 2. Event Bus 81 | 2.1 Decoupled, generic, not context aware components 82 | 2.2 Everyone talks, but only controllers respond 83 | 3. View helpers 84 | 3.1 Rails conformity 85 | 86 | # (JS) Testing 87 | 1. Unit Testing (Black Box) of models 88 | 2. Unit Testing (White Box) of controllers 89 | 3. Acceptance Testing with Capybara/Phantom 90 | 91 | # FUTURE 92 | Things we are working on (on going projects) 93 | - modules, AMD, dynamic bundling 94 | 2. Real time (the state now) 95 | 3. JavaScript and the API. 96 | - Future of Rails 97 | - node.js 98 | - Do we actually need web-servers? 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/theme/scss/_base.scss: -------------------------------------------------------------------------------- 1 | @import "compass/reset"; 2 | @import "compass/css3/border-radius"; 3 | @import "compass/css3/box"; 4 | @import "compass/css3/box-shadow"; 5 | @import "compass/css3/box-sizing"; 6 | @import "compass/css3/images"; 7 | @import "compass/css3/text-shadow"; 8 | @import "compass/css3/background-size"; 9 | @import "compass/css3/transform"; 10 | @import "compass/css3/transition"; 11 | 12 | @mixin font-smoothing($val: antialiased) { 13 | -webkit-font-smoothing: $val; 14 | -moz-font-smoothing: $val; 15 | -ms-font-smoothing: $val; 16 | -o-font-smoothing: $val; 17 | } 18 | 19 | @mixin flexbox { 20 | display: -webkit-box !important; 21 | display: -moz-box !important; 22 | display: -ms-box !important; 23 | display: -o-box !important; 24 | display: box !important; 25 | } 26 | 27 | @mixin flex-center-center { 28 | @include box-orient(vertical); 29 | @include box-align(center); 30 | @include box-pack(center); 31 | } 32 | 33 | @mixin flex-left-center { 34 | @include box-orient(vertical); 35 | @include box-align(left); 36 | @include box-pack(center); 37 | } 38 | 39 | @mixin flex-right-center { 40 | @include box-orient(vertical); 41 | @include box-align(end); 42 | @include box-pack(center); 43 | } 44 | 45 | /** 46 | * Base SlideDeck Styles 47 | */ 48 | html { 49 | height: 100%; 50 | overflow: hidden; 51 | } 52 | 53 | body { 54 | margin: 0; 55 | padding: 0; 56 | 57 | opacity: 0; 58 | 59 | height: 100%; 60 | min-height: 740px; 61 | width: 100%; 62 | 63 | overflow: hidden; 64 | 65 | color: #fff; 66 | @include font-smoothing(antialiased); 67 | @include transition(opacity 800ms ease-in 100ms); // Add small delay to prevent jank. 68 | 69 | &.loaded { 70 | opacity: 1 !important; 71 | } 72 | } 73 | 74 | input, button { 75 | vertical-align: middle; 76 | } 77 | 78 | slides > slide[hidden] { 79 | display: none !important; 80 | } 81 | 82 | slides { 83 | width: 100%; 84 | height: 100%; 85 | position: absolute; 86 | left: 0; 87 | top: 0; 88 | @include transform(translate3d(0, 0, 0)); 89 | @include perspective(1000); 90 | @include transform-style(preserve-3d); 91 | @include transition(opacity 800ms ease-in 100ms); // Add small delay to prevent jank. 92 | } 93 | 94 | slides > slide { 95 | display: block; 96 | position: absolute; 97 | overflow: hidden; 98 | left: 50%; 99 | top: 50%; 100 | @include box-sizing(border-box); 101 | } 102 | 103 | /* Slide styles */ 104 | 105 | 106 | /*article.fill iframe { 107 | position: absolute; 108 | left: 0; 109 | top: 0; 110 | width: 100%; 111 | height: 100%; 112 | 113 | border: 0; 114 | margin: 0; 115 | 116 | @include border-radius(10px); 117 | 118 | z-index: -1; 119 | } 120 | 121 | slide.fill { 122 | background-repeat: no-repeat; 123 | @include background-size(cover); 124 | } 125 | 126 | slide.fill img { 127 | position: absolute; 128 | left: 0; 129 | top: 0; 130 | min-width: 100%; 131 | min-height: 100%; 132 | 133 | z-index: -1; 134 | } 135 | */ 136 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/slide-controller.js: -------------------------------------------------------------------------------- 1 | (function(window) { 2 | 3 | var ORIGIN_ = location.protocol + '//' + location.host; 4 | 5 | function SlideController() { 6 | this.popup = null; 7 | this.isPopup = window.opener; 8 | 9 | if (this.setupDone()) { 10 | window.addEventListener('message', this.onMessage_.bind(this), false); 11 | 12 | // Close popups if we reload the main window. 13 | window.addEventListener('beforeunload', function(e) { 14 | if (this.popup) { 15 | this.popup.close(); 16 | } 17 | }.bind(this), false); 18 | } 19 | } 20 | 21 | SlideController.PRESENTER_MODE_PARAM = 'presentme'; 22 | 23 | SlideController.prototype.setupDone = function() { 24 | var params = location.search.substring(1).split('&').map(function(el) { 25 | return el.split('='); 26 | }); 27 | 28 | var presentMe = null; 29 | for (var i = 0, param; param = params[i]; ++i) { 30 | if (param[0].toLowerCase() == SlideController.PRESENTER_MODE_PARAM) { 31 | presentMe = param[1] == 'true'; 32 | break; 33 | } 34 | } 35 | 36 | if (presentMe !== null) { 37 | localStorage.ENABLE_PRESENTOR_MODE = presentMe; 38 | // TODO: use window.history.pushState to update URL instead of the redirect. 39 | if (window.history.replaceState) { 40 | window.history.replaceState({}, '', location.pathname); 41 | } else { 42 | location.replace(location.pathname); 43 | return false; 44 | } 45 | } 46 | 47 | var enablePresenterMode = localStorage.getItem('ENABLE_PRESENTOR_MODE'); 48 | if (enablePresenterMode && JSON.parse(enablePresenterMode)) { 49 | // Only open popup from main deck. Don't want recursive popup opening! 50 | if (!this.isPopup) { 51 | var opts = 'menubar=no,location=yes,resizable=yes,scrollbars=no,status=no'; 52 | this.popup = window.open(location.href, 'mywindow', opts); 53 | 54 | // Loading in the popup? Trigger the hotkey for turning presenter mode on. 55 | this.popup.addEventListener('load', function(e) { 56 | var evt = this.popup.document.createEvent('Event'); 57 | evt.initEvent('keydown', true, true); 58 | evt.keyCode = 'P'.charCodeAt(0); 59 | this.popup.document.dispatchEvent(evt); 60 | // this.popup.document.body.classList.add('with-notes'); 61 | // document.body.classList.add('popup'); 62 | }.bind(this), false); 63 | } 64 | } 65 | 66 | return true; 67 | } 68 | 69 | SlideController.prototype.onMessage_ = function(e) { 70 | var data = e.data; 71 | 72 | // Restrict messages to being from this origin. Allow local developmet 73 | // from file:// though. 74 | // TODO: It would be dope if FF implemented location.origin! 75 | if (e.origin != ORIGIN_ && ORIGIN_.indexOf('file://') != 0) { 76 | alert('Someone tried to postMessage from an unknown origin'); 77 | return; 78 | } 79 | 80 | // if (e.source.location.hostname != 'localhost') { 81 | // alert('Someone tried to postMessage from an unknown origin'); 82 | // return; 83 | // } 84 | 85 | if ('keyCode' in data) { 86 | var evt = document.createEvent('Event'); 87 | evt.initEvent('keydown', true, true); 88 | evt.keyCode = data.keyCode; 89 | document.dispatchEvent(evt); 90 | } 91 | }; 92 | 93 | SlideController.prototype.sendMsg = function(msg) { 94 | // // Send message to popup window. 95 | // if (this.popup) { 96 | // this.popup.postMessage(msg, ORIGIN_); 97 | // } 98 | 99 | // Send message to main window. 100 | if (this.isPopup) { 101 | // TODO: It would be dope if FF implemented location.origin. 102 | window.opener.postMessage(msg, '*'); 103 | } 104 | }; 105 | 106 | window.SlideController = SlideController; 107 | 108 | })(window); 109 | 110 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/.idea/projectCodeStyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/modernizr.custom.45394.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.5.3 (Custom Build) | MIT & BSD 2 | * Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexbox_legacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-mq-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function C(a){i.cssText=a}function D(a,b){return C(m.join(a+";")+(b||""))}function E(a,b){return typeof a===b}function F(a,b){return!!~(""+a).indexOf(b)}function G(a,b){for(var d in a)if(i[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function H(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:E(f,"function")?f.bind(d||b):f}return!1}function I(a,b,c){var d=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+o.join(d+" ")+d).split(" ");return E(b,"string")||E(b,"undefined")?G(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),H(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d",a,""].join(""),k.id=g,(l?k:m).innerHTML+=h,m.appendChild(k),l||(m.style.background="",f.appendChild(m)),i=c(k,a),l?k.parentNode.removeChild(k):m.parentNode.removeChild(m),!!i},y=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return x("@media "+b+" { #"+g+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},z=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=E(e[d],"function"),E(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),A={}.hasOwnProperty,B;!E(A,"undefined")&&!E(A.call,"undefined")?B=function(a,b){return A.call(a,b)}:B=function(a,b){return b in a&&E(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=v.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(v.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(v.call(arguments)))};return e});var J=function(c,d){var f=c.join(""),g=d.length;x(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch||(j.touch&&j.touch.offsetTop)===9,e.csstransforms3d=(j.csstransforms3d&&j.csstransforms3d.offsetLeft)===9&&j.csstransforms3d.offsetHeight===3,e.generatedcontent=(j.generatedcontent&&j.generatedcontent.offsetHeight)>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",m.join("touch-enabled),("),g,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",m.join("transform-3d),("),g,")","{#csstransforms3d{left:9px;position:absolute;height:3px;}}"].join(""),['#generatedcontent:after{content:"',k,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){return I("flexOrder")},r["flexbox-legacy"]=function(){return I("boxDirection")},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!E(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){try{var d=b.createElement("canvas"),e;e=!(!a.WebGLRenderingContext||!d.getContext("experimental-webgl")&&!d.getContext("webgl")),d=c}catch(f){e=!1}return e},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){return!!a.openDatabase},r.indexedDB=function(){return!!I("indexedDB",a)},r.hashchange=function(){return z("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},r.websockets=function(){for(var b=-1,c=o.length;++b122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), 9 | l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, 10 | q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, 11 | q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, 12 | "");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), 13 | a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} 14 | for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], 18 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], 19 | H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], 20 | J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ 21 | I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), 22 | ["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", 23 | /^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), 24 | ["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", 25 | hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= 26 | !k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p0&&(g.splice(m-1,2),m-=2);m=q.pkgs[g=b[0]];b=b.join("/");m&&b===g+"/"+m.main&&(b=g)}else b.indexOf("./")=== 9 | 0&&(b=b.substring(2));return b}function l(b,f){var g=b?b.indexOf("!"):-1,m=null,a=f?f.name:null,h=b,e,d;g!==-1&&(m=b.substring(0,g),b=b.substring(g+1,b.length));m&&(m=c(m,a));b&&(m?e=(g=n[m])&&g.normalize?g.normalize(b,function(b){return c(b,a)}):c(b,a):(e=c(b,a),d=G[e],d||(d=i.nameToUrl(b,null,f),G[e]=d)));return{prefix:m,name:e,parentMap:f,url:d,originalName:h,fullName:m?m+"!"+(e||""):e}}function j(){var b=!0,f=q.priorityWait,g,a;if(f){for(a=0;g=f[a];a++)if(!s[g]){b=!1;break}b&&delete q.priorityWait}return b} 10 | function k(b,f,g){return function(){var a=ha.call(arguments,0),c;if(g&&K(c=a[a.length-1]))c.__requireJsBuild=!0;a.push(f);return b.apply(null,a)}}function t(b,f,g){f=k(g||i.require,b,f);$(f,{nameToUrl:k(i.nameToUrl,b),toUrl:k(i.toUrl,b),defined:k(i.requireDefined,b),specified:k(i.requireSpecified,b),isBrowser:d.isBrowser});return f}function p(b){var f,g,a,c=b.callback,h=b.map,e=h.fullName,ca=b.deps;a=b.listeners;var j=q.requireExecCb||d.execCb;if(c&&K(c)){if(q.catchError.define)try{g=j(e,b.callback, 11 | ca,n[e])}catch(k){f=k}else g=j(e,b.callback,ca,n[e]);if(e)(c=b.cjsModule)&&c.exports!==r&&c.exports!==n[e]?g=n[e]=b.cjsModule.exports:g===r&&b.usingExports?g=n[e]:(n[e]=g,H[e]&&(T[e]=!0))}else e&&(g=n[e]=c,H[e]&&(T[e]=!0));if(x[b.id])delete x[b.id],b.isDone=!0,i.waitCount-=1,i.waitCount===0&&(J=[]);delete M[e];if(d.onResourceLoad&&!b.placeholder)d.onResourceLoad(i,h,b.depArray);if(f)return g=(e?l(e).url:"")||f.fileName||f.sourceURL,a=f.moduleTree,f=P("defineerror",'Error evaluating module "'+e+'" at location "'+ 12 | g+'":\n'+f+"\nfileName:"+g+"\nlineNumber: "+(f.lineNumber||f.line),f),f.moduleName=e,f.moduleTree=a,d.onError(f);for(f=0;c=a[f];f++)c(g);return r}function u(b,f){return function(g){b.depDone[f]||(b.depDone[f]=!0,b.deps[f]=g,b.depCount-=1,b.depCount||p(b))}}function o(b,f){var g=f.map,a=g.fullName,c=g.name,h=N[b]||(N[b]=n[b]),e;if(!f.loading)f.loading=!0,e=function(b){f.callback=function(){return b};p(f);s[f.id]=!0;A()},e.fromText=function(b,f){var g=Q;s[b]=!1;i.scriptCount+=1;i.fake[b]=!0;g&&(Q=!1); 13 | d.exec(f);g&&(Q=!0);i.completeLoad(b)},a in n?e(n[a]):h.load(c,t(g.parentMap,!0,function(b,a){var c=[],e,m;for(e=0;m=b[e];e++)m=l(m,g.parentMap),b[e]=m.fullName,m.prefix||c.push(b[e]);f.moduleDeps=(f.moduleDeps||[]).concat(c);return i.require(b,a)}),e,q)}function y(b){x[b.id]||(x[b.id]=b,J.push(b),i.waitCount+=1)}function D(b){this.listeners.push(b)}function v(b,f){var g=b.fullName,a=b.prefix,c=a?N[a]||(N[a]=n[a]):null,h,e;g&&(h=M[g]);if(!h&&(e=!0,h={id:(a&&!c?O++ +"__p@:":"")+(g||"__r@"+O++),map:b, 14 | depCount:0,depDone:[],depCallbacks:[],deps:[],listeners:[],add:D},B[h.id]=!0,g&&(!a||N[a])))M[g]=h;a&&!c?(g=l(a),a in n&&!n[a]&&(delete n[a],delete R[g.url]),a=v(g,!0),a.add(function(){var f=l(b.originalName,b.parentMap),f=v(f,!0);h.placeholder=!0;f.add(function(b){h.callback=function(){return b};p(h)})})):e&&f&&(s[h.id]=!1,i.paused.push(h),y(h));return h}function C(b,f,a,c){var b=l(b,c),d=b.name,h=b.fullName,e=v(b),j=e.id,k=e.deps,o;if(h){if(h in n||s[j]===!0||h==="jquery"&&q.jQuery&&q.jQuery!== 15 | a().fn.jquery)return;B[j]=!0;s[j]=!0;h==="jquery"&&a&&W(a())}e.depArray=f;e.callback=a;for(a=0;a0)return r;if(q.priorityWait)if(j())A();else return r;for(h in s)if(!(h in L)&&(c=!0,!s[h]))if(b)a+=h+" ";else if(l=!0,h.indexOf("!")===-1){k=[];break}else(e=M[h]&&M[h].moduleDeps)&&k.push.apply(k,e);if(!c&&!i.waitCount)return r;if(b&&a)return b=P("timeout","Load timeout for modules: "+a),b.requireType="timeout",b.requireModules=a,b.contextName=i.contextName,d.onError(b); 18 | if(l&&k.length)for(a=0;h=x[k[a]];a++)if(h=F(h,{})){z(h,{});break}if(!b&&(l||i.scriptCount)){if((I||da)&&!X)X=setTimeout(function(){X=0;E()},50);return r}if(i.waitCount){for(a=0;h=J[a];a++)z(h,{});i.paused.length&&A();Y<5&&(Y+=1,E())}Y=0;d.checkReadyState();return r}var i,A,q={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},catchError:{}},S=[],B={require:!0,exports:!0,module:!0},G={},n={},s={},x={},J=[],R={},O=0,M={},N={},H={},T={},Z=0;W=function(b){if(!i.jQuery&&(b=b||(typeof jQuery!=="undefined"?jQuery: 19 | null))&&!(q.jQuery&&b.fn.jquery!==q.jQuery)&&("holdReady"in b||"readyWait"in b))if(i.jQuery=b,w(["jquery",[],function(){return jQuery}]),i.scriptCount)V(b,!0),i.jQueryIncremented=!0};A=function(){var b,a,c,l,k,h;i.takeGlobalQueue();Z+=1;if(i.scriptCount<=0)i.scriptCount=0;for(;S.length;)if(b=S.shift(),b[0]===null)return d.onError(P("mismatch","Mismatched anonymous define() module: "+b[b.length-1]));else w(b);if(!q.priorityWait||j())for(;i.paused.length;){k=i.paused;i.pausedCount+=k.length;i.paused= 20 | [];for(l=0;b=k[l];l++)a=b.map,c=a.url,h=a.fullName,a.prefix?o(a.prefix,b):!R[c]&&!s[h]&&((q.requireLoad||d.load)(i,h,c),c.indexOf("empty:")!==0&&(R[c]=!0));i.startTime=(new Date).getTime();i.pausedCount-=k.length}Z===1&&E();Z-=1;return r};i={contextName:a,config:q,defQueue:S,waiting:x,waitCount:0,specified:B,loaded:s,urlMap:G,urlFetched:R,scriptCount:0,defined:n,paused:[],pausedCount:0,plugins:N,needFullExec:H,fake:{},fullExec:T,managerCallbacks:M,makeModuleMap:l,normalize:c,configure:function(b){var a, 21 | c,d;b.baseUrl&&b.baseUrl.charAt(b.baseUrl.length-1)!=="/"&&(b.baseUrl+="/");a=q.paths;d=q.pkgs;$(q,b,!0);if(b.paths){for(c in b.paths)c in L||(a[c]=b.paths[c]);q.paths=a}if((a=b.packagePaths)||b.packages){if(a)for(c in a)c in L||aa(d,a[c],c);b.packages&&aa(d,b.packages);q.pkgs=d}if(b.priority)c=i.requireWait,i.requireWait=!1,A(),i.require(b.priority),A(),i.requireWait=c,q.priorityWait=b.priority;if(b.deps||b.callback)i.require(b.deps||[],b.callback)},requireDefined:function(b,a){return l(b,a).fullName in 22 | n},requireSpecified:function(b,a){return l(b,a).fullName in B},require:function(b,c,g){if(typeof b==="string"){if(K(c))return d.onError(P("requireargs","Invalid require call"));if(d.get)return d.get(i,b,c);c=l(b,c);b=c.fullName;return!(b in n)?d.onError(P("notloaded","Module name '"+c.fullName+"' has not been loaded yet for context: "+a)):n[b]}(b&&b.length||c)&&C(null,b,c,g);if(!i.requireWait)for(;!i.scriptCount&&i.paused.length;)A();return i.require},takeGlobalQueue:function(){U.length&&(ja.apply(i.defQueue, 23 | [i.defQueue.length-1,0].concat(U)),U=[])},completeLoad:function(b){var a;for(i.takeGlobalQueue();S.length;)if(a=S.shift(),a[0]===null){a[0]=b;break}else if(a[0]===b)break;else w(a),a=null;a?w(a):w([b,[],b==="jquery"&&typeof jQuery!=="undefined"?function(){return jQuery}:null]);d.isAsync&&(i.scriptCount-=1);A();d.isAsync||(i.scriptCount-=1)},toUrl:function(b,a){var c=b.lastIndexOf("."),d=null;c!==-1&&(d=b.substring(c,b.length),b=b.substring(0,c));return i.nameToUrl(b,d,a)},nameToUrl:function(b,a,g){var l, 24 | k,h,e,j=i.config,b=c(b,g&&g.fullName);if(d.jsExtRegExp.test(b))a=b+(a?a:"");else{l=j.paths;k=j.pkgs;g=b.split("/");for(e=g.length;e>0;e--)if(h=g.slice(0,e).join("/"),l[h]){g.splice(0,e,l[h]);break}else if(h=k[h]){b=b===h.name?h.location+"/"+h.main:h.location;g.splice(0,e,b);break}a=g.join("/")+(a||".js");a=(a.charAt(0)==="/"||a.match(/^[\w\+\.\-]+:/)?"":j.baseUrl)+a}return j.urlArgs?a+((a.indexOf("?")===-1?"?":"&")+j.urlArgs):a}};i.jQueryCheck=W;i.resume=A;return i}function ka(){var a,c,d;if(C&&C.readyState=== 25 | "interactive")return C;a=document.getElementsByTagName("script");for(c=a.length-1;c>-1&&(d=a[c]);c--)if(d.readyState==="interactive")return C=d;return null}var la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/require\(\s*["']([^'"\s]+)["']\s*\)/g,fa=/^\.\//,ba=/\.js$/,O=Object.prototype.toString,u=Array.prototype,ha=u.slice,ja=u.splice,I=!!(typeof window!=="undefined"&&navigator&&document),da=!I&&typeof importScripts!=="undefined",na=I&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/, 26 | ea=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",L={},D={},U=[],C=null,Y=0,Q=!1,ia={require:!0,module:!0,exports:!0},d,u={},J,y,v,E,o,w,F,B,z,W,X;if(typeof define==="undefined"){if(typeof requirejs!=="undefined")if(K(requirejs))return;else u=requirejs,requirejs=r;typeof require!=="undefined"&&!K(require)&&(u=require,require=r);d=requirejs=function(a,c,d){var j="_",k;!G(a)&&typeof a!=="string"&&(k=a,G(c)?(a=c,c=d):a=[]);if(k&&k.context)j=k.context;d=D[j]||(D[j]=ga(j));k&&d.configure(k); 27 | return d.require(a,c)};d.config=function(a){return d(a)};require||(require=d);d.toUrl=function(a){return D._.toUrl(a)};d.version="1.0.8";d.jsExtRegExp=/^\/|:|\?|\.js$/;y=d.s={contexts:D,skipAsync:{}};if(d.isAsync=d.isBrowser=I)if(v=y.head=document.getElementsByTagName("head")[0],E=document.getElementsByTagName("base")[0])v=y.head=E.parentNode;d.onError=function(a){throw a;};d.load=function(a,c,l){d.resourcesReady(!1);a.scriptCount+=1;d.attach(l,a,c);if(a.jQuery&&!a.jQueryIncremented)V(a.jQuery,!0), 28 | a.jQueryIncremented=!0};define=function(a,c,d){var j,k;typeof a!=="string"&&(d=c,c=a,a=null);G(c)||(d=c,c=[]);!c.length&&K(d)&&d.length&&(d.toString().replace(la,"").replace(ma,function(a,d){c.push(d)}),c=(d.length===1?["require"]:["require","exports","module"]).concat(c));if(Q&&(j=J||ka()))a||(a=j.getAttribute("data-requiremodule")),k=D[j.getAttribute("data-requirecontext")];(k?k.defQueue:U).push([a,c,d]);return r};define.amd={multiversion:!0,plugins:!0,jQuery:!0};d.exec=function(a){return eval(a)}; 29 | d.execCb=function(a,c,d,j){return c.apply(j,d)};d.addScriptToDom=function(a){J=a;E?v.insertBefore(a,E):v.appendChild(a);J=null};d.onScriptLoad=function(a){var c=a.currentTarget||a.srcElement,l;if(a.type==="load"||c&&na.test(c.readyState))C=null,a=c.getAttribute("data-requirecontext"),l=c.getAttribute("data-requiremodule"),D[a].completeLoad(l),c.detachEvent&&!ea?c.detachEvent("onreadystatechange",d.onScriptLoad):c.removeEventListener("load",d.onScriptLoad,!1)};d.attach=function(a,c,l,j,k,o){var p; 30 | if(I)return j=j||d.onScriptLoad,p=c&&c.config&&c.config.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),p.type=k||c&&c.config.scriptType||"text/javascript",p.charset="utf-8",p.async=!y.skipAsync[a],c&&p.setAttribute("data-requirecontext",c.contextName),p.setAttribute("data-requiremodule",l),p.attachEvent&&!(p.attachEvent.toString&&p.attachEvent.toString().indexOf("[native code]")<0)&&!ea?(Q=!0,o?p.onreadystatechange=function(){if(p.readyState=== 31 | "loaded")p.onreadystatechange=null,p.attachEvent("onreadystatechange",j),o(p)}:p.attachEvent("onreadystatechange",j)):p.addEventListener("load",j,!1),p.src=a,o||d.addScriptToDom(p),p;else da&&(importScripts(a),c.completeLoad(l));return null};if(I){o=document.getElementsByTagName("script");for(B=o.length-1;B>-1&&(w=o[B]);B--){if(!v)v=w.parentNode;if(F=w.getAttribute("data-main")){if(!u.baseUrl)o=F.split("/"),w=o.pop(),o=o.length?o.join("/")+"/":"./",u.baseUrl=o,F=w.replace(ba,"");u.deps=u.deps?u.deps.concat(F): 32 | [F];break}}}d.checkReadyState=function(){var a=y.contexts,c;for(c in a)if(!(c in L)&&a[c].waitCount)return;d.resourcesReady(!0)};d.resourcesReady=function(a){var c,l;d.resourcesDone=a;if(d.resourcesDone)for(l in a=y.contexts,a)if(!(l in L)&&(c=a[l],c.jQueryIncremented))V(c.jQuery,!1),c.jQueryIncremented=!1};d.pageLoaded=function(){if(document.readyState!=="complete")document.readyState="complete"};if(I&&document.addEventListener&&!document.readyState)document.readyState="loading",window.addEventListener("load", 33 | d.pageLoaded,!1);d(u);if(d.isAsync&&typeof setTimeout!=="undefined")z=y.contexts[u.context||"_"],z.requireWait=!0,setTimeout(function(){z.requireWait=!1;z.scriptCount||z.resume();d.checkReadyState()},0)}})(); 34 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/polyfills/history.min.js: -------------------------------------------------------------------------------- 1 | (function(a,b){"use strict";var c=a.console||b,d=a.document,e=a.navigator,f=a.sessionStorage||!1,g=a.setTimeout,h=a.clearTimeout,i=a.setInterval,j=a.clearInterval,k=a.JSON,l=a.alert,m=a.History=a.History||{},n=a.history;k.stringify=k.stringify||k.encode,k.parse=k.parse||k.decode;if(typeof m.init!="undefined")throw new Error("History.js Core has already been loaded...");m.init=function(){return typeof m.Adapter=="undefined"?!1:(typeof m.initCore!="undefined"&&m.initCore(),typeof m.initHtml4!="undefined"&&m.initHtml4(),!0)},m.initCore=function(){if(typeof m.initCore.initialized!="undefined")return!1;m.initCore.initialized=!0,m.options=m.options||{},m.options.hashChangeInterval=m.options.hashChangeInterval||100,m.options.safariPollInterval=m.options.safariPollInterval||500,m.options.doubleCheckInterval=m.options.doubleCheckInterval||500,m.options.storeInterval=m.options.storeInterval||1e3,m.options.busyDelay=m.options.busyDelay||250,m.options.debug=m.options.debug||!1,m.options.initialTitle=m.options.initialTitle||d.title,m.intervalList=[],m.clearAllIntervals=function(){var a,b=m.intervalList;if(typeof b!="undefined"&&b!==null){for(a=0;a")&&c[0]);return a>4?a:!1}();return a},m.isInternetExplorer=function(){var a=m.isInternetExplorer.cached=typeof m.isInternetExplorer.cached!="undefined"?m.isInternetExplorer.cached:Boolean(m.getInternetExplorerMajorVersion());return a},m.emulated={pushState:!Boolean(a.history&&a.history.pushState&&a.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(e.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(e.userAgent)),hashChange:Boolean(!("onhashchange"in a||"onhashchange"in d)||m.isInternetExplorer()&&m.getInternetExplorerMajorVersion()<8)},m.enabled=!m.emulated.pushState,m.bugs={setHash:Boolean(!m.emulated.pushState&&e.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)),safariPoll:Boolean(!m.emulated.pushState&&e.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)),ieDoubleCheck:Boolean(m.isInternetExplorer()&&m.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(m.isInternetExplorer()&&m.getInternetExplorerMajorVersion()<7)},m.isEmptyObject=function(a){for(var b in a)return!1;return!0},m.cloneObject=function(a){var b,c;return a?(b=k.stringify(a),c=k.parse(b)):c={},c},m.getRootUrl=function(){var a=d.location.protocol+"//"+(d.location.hostname||d.location.host);if(d.location.port||!1)a+=":"+d.location.port;return a+="/",a},m.getBaseHref=function(){var a=d.getElementsByTagName("base"),b=null,c="";return a.length===1&&(b=a[0],c=b.href.replace(/[^\/]+$/,"")),c=c.replace(/\/+$/,""),c&&(c+="/"),c},m.getBaseUrl=function(){var a=m.getBaseHref()||m.getBasePageUrl()||m.getRootUrl();return a},m.getPageUrl=function(){var a=m.getState(!1,!1),b=(a||{}).url||d.location.href,c;return c=b.replace(/\/+$/,"").replace(/[^\/]+$/,function(a,b,c){return/\./.test(a)?a:a+"/"}),c},m.getBasePageUrl=function(){var a=d.location.href.replace(/[#\?].*/,"").replace(/[^\/]+$/,function(a,b,c){return/[^\/]$/.test(a)?"":a}).replace(/\/+$/,"")+"/";return a},m.getFullUrl=function(a,b){var c=a,d=a.substring(0,1);return b=typeof b=="undefined"?!0:b,/[a-z]+\:\/\//.test(a)||(d==="/"?c=m.getRootUrl()+a.replace(/^\/+/,""):d==="#"?c=m.getPageUrl().replace(/#.*/,"")+a:d==="?"?c=m.getPageUrl().replace(/[\?#].*/,"")+a:b?c=m.getBaseUrl()+a.replace(/^(\.\/)+/,""):c=m.getBasePageUrl()+a.replace(/^(\.\/)+/,"")),c.replace(/\#$/,"")},m.getShortUrl=function(a){var b=a,c=m.getBaseUrl(),d=m.getRootUrl();return m.emulated.pushState&&(b=b.replace(c,"")),b=b.replace(d,"/"),m.isTraditionalAnchor(b)&&(b="./"+b),b=b.replace(/^(\.\/)+/g,"./").replace(/\#$/,""),b},m.store={},m.idToState=m.idToState||{},m.stateToId=m.stateToId||{},m.urlToId=m.urlToId||{},m.storedStates=m.storedStates||[],m.savedStates=m.savedStates||[],m.normalizeStore=function(){m.store.idToState=m.store.idToState||{},m.store.urlToId=m.store.urlToId||{},m.store.stateToId=m.store.stateToId||{}},m.getState=function(a,b){typeof a=="undefined"&&(a=!0),typeof b=="undefined"&&(b=!0);var c=m.getLastSavedState();return!c&&b&&(c=m.createStateObject()),a&&(c=m.cloneObject(c),c.url=c.cleanUrl||c.url),c},m.getIdByState=function(a){var b=m.extractId(a.url),c;if(!b){c=m.getStateString(a);if(typeof m.stateToId[c]!="undefined")b=m.stateToId[c];else if(typeof m.store.stateToId[c]!="undefined")b=m.store.stateToId[c];else{for(;;){b=(new Date).getTime()+String(Math.random()).replace(/\D/g,"");if(typeof m.idToState[b]=="undefined"&&typeof m.store.idToState[b]=="undefined")break}m.stateToId[c]=b,m.idToState[b]=a}}return b},m.normalizeState=function(a){var b,c;if(!a||typeof a!="object")a={};if(typeof a.normalized!="undefined")return a;if(!a.data||typeof a.data!="object")a.data={};b={},b.normalized=!0,b.title=a.title||"",b.url=m.getFullUrl(m.unescapeString(a.url||d.location.href)),b.hash=m.getShortUrl(b.url),b.data=m.cloneObject(a.data),b.id=m.getIdByState(b),b.cleanUrl=b.url.replace(/\??\&_suid.*/,""),b.url=b.cleanUrl,c=!m.isEmptyObject(b.data);if(b.title||c)b.hash=m.getShortUrl(b.url).replace(/\??\&_suid.*/,""),/\?/.test(b.hash)||(b.hash+="?"),b.hash+="&_suid="+b.id;return b.hashedUrl=m.getFullUrl(b.hash),(m.emulated.pushState||m.bugs.safariPoll)&&m.hasUrlDuplicate(b)&&(b.url=b.hashedUrl),b},m.createStateObject=function(a,b,c){var d={data:a,title:b,url:c};return d=m.normalizeState(d),d},m.getStateById=function(a){a=String(a);var c=m.idToState[a]||m.store.idToState[a]||b;return c},m.getStateString=function(a){var b,c,d;return b=m.normalizeState(a),c={data:b.data,title:a.title,url:a.url},d=k.stringify(c),d},m.getStateId=function(a){var b,c;return b=m.normalizeState(a),c=b.id,c},m.getHashByState=function(a){var b,c;return b=m.normalizeState(a),c=b.hash,c},m.extractId=function(a){var b,c,d;return c=/(.*)\&_suid=([0-9]+)$/.exec(a),d=c?c[1]||a:a,b=c?String(c[2]||""):"",b||!1},m.isTraditionalAnchor=function(a){var b=!/[\/\?\.]/.test(a);return b},m.extractState=function(a,b){var c=null,d,e;return b=b||!1,d=m.extractId(a),d&&(c=m.getStateById(d)),c||(e=m.getFullUrl(a),d=m.getIdByUrl(e)||!1,d&&(c=m.getStateById(d)),!c&&b&&!m.isTraditionalAnchor(a)&&(c=m.createStateObject(null,null,e))),c},m.getIdByUrl=function(a){var c=m.urlToId[a]||m.store.urlToId[a]||b;return c},m.getLastSavedState=function(){return m.savedStates[m.savedStates.length-1]||b},m.getLastStoredState=function(){return m.storedStates[m.storedStates.length-1]||b},m.hasUrlDuplicate=function(a){var b=!1,c;return c=m.extractState(a.url),b=c&&c.id!==a.id,b},m.storeState=function(a){return m.urlToId[a.url]=a.id,m.storedStates.push(m.cloneObject(a)),a},m.isLastSavedState=function(a){var b=!1,c,d,e;return m.savedStates.length&&(c=a.id,d=m.getLastSavedState(),e=d.id,b=c===e),b},m.saveState=function(a){return m.isLastSavedState(a)?!1:(m.savedStates.push(m.cloneObject(a)),!0)},m.getStateByIndex=function(a){var b=null;return typeof a=="undefined"?b=m.savedStates[m.savedStates.length-1]:a<0?b=m.savedStates[m.savedStates.length+a]:b=m.savedStates[a],b},m.getHash=function(){var a=m.unescapeHash(d.location.hash);return a},m.unescapeString=function(b){var c=b,d;for(;;){d=a.unescape(c);if(d===c)break;c=d}return c},m.unescapeHash=function(a){var b=m.normalizeHash(a);return b=m.unescapeString(b),b},m.normalizeHash=function(a){var b=a.replace(/[^#]*#/,"").replace(/#.*/,"");return b},m.setHash=function(a,b){var c,e,f;return b!==!1&&m.busy()?(m.pushQueue({scope:m,callback:m.setHash,args:arguments,queue:b}),!1):(c=m.escapeHash(a),m.busy(!0),e=m.extractState(a,!0),e&&!m.emulated.pushState?m.pushState(e.data,e.title,e.url,!1):d.location.hash!==c&&(m.bugs.setHash?(f=m.getPageUrl(),m.pushState(null,null,f+"#"+c,!1)):d.location.hash=c),m)},m.escapeHash=function(b){var c=m.normalizeHash(b);return c=a.escape(c),m.bugs.hashEscape||(c=c.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?")),c},m.getHashByUrl=function(a){var b=String(a).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");return b=m.unescapeHash(b),b},m.setTitle=function(a){var b=a.title,c;b||(c=m.getStateByIndex(0),c&&c.url===a.url&&(b=c.title||m.options.initialTitle));try{d.getElementsByTagName("title")[0].innerHTML=b.replace("<","<").replace(">",">").replace(" & "," & ")}catch(e){}return d.title=b,m},m.queues=[],m.busy=function(a){typeof a!="undefined"?m.busy.flag=a:typeof m.busy.flag=="undefined"&&(m.busy.flag=!1);if(!m.busy.flag){h(m.busy.timeout);var b=function(){var a,c,d;if(m.busy.flag)return;for(a=m.queues.length-1;a>=0;--a){c=m.queues[a];if(c.length===0)continue;d=c.shift(),m.fireQueueItem(d),m.busy.timeout=g(b,m.options.busyDelay)}};m.busy.timeout=g(b,m.options.busyDelay)}return m.busy.flag},m.busy.flag=!1,m.fireQueueItem=function(a){return a.callback.apply(a.scope||m,a.args||[])},m.pushQueue=function(a){return m.queues[a.queue||0]=m.queues[a.queue||0]||[],m.queues[a.queue||0].push(a),m},m.queue=function(a,b){return typeof a=="function"&&(a={callback:a}),typeof b!="undefined"&&(a.queue=b),m.busy()?m.pushQueue(a):m.fireQueueItem(a),m},m.clearQueue=function(){return m.busy.flag=!1,m.queues=[],m},m.stateChanged=!1,m.doubleChecker=!1,m.doubleCheckComplete=function(){return m.stateChanged=!0,m.doubleCheckClear(),m},m.doubleCheckClear=function(){return m.doubleChecker&&(h(m.doubleChecker),m.doubleChecker=!1),m},m.doubleCheck=function(a){return m.stateChanged=!1,m.doubleCheckClear(),m.bugs.ieDoubleCheck&&(m.doubleChecker=g(function(){return m.doubleCheckClear(),m.stateChanged||a(),!0},m.options.doubleCheckInterval)),m},m.safariStatePoll=function(){var b=m.extractState(d.location.href),c;if(!m.isLastSavedState(b))c=b;else return;return c||(c=m.createStateObject()),m.Adapter.trigger(a,"popstate"),m},m.back=function(a){return a!==!1&&m.busy()?(m.pushQueue({scope:m,callback:m.back,args:arguments,queue:a}),!1):(m.busy(!0),m.doubleCheck(function(){m.back(!1)}),n.go(-1),!0)},m.forward=function(a){return a!==!1&&m.busy()?(m.pushQueue({scope:m,callback:m.forward,args:arguments,queue:a}),!1):(m.busy(!0),m.doubleCheck(function(){m.forward(!1)}),n.go(1),!0)},m.go=function(a,b){var c;if(a>0)for(c=1;c<=a;++c)m.forward(b);else{if(!(a<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(c=-1;c>=a;--c)m.back(b)}return m};if(m.emulated.pushState){var o=function(){};m.pushState=m.pushState||o,m.replaceState=m.replaceState||o}else m.onPopState=function(b,c){var e=!1,f=!1,g,h;return m.doubleCheckComplete(),g=m.getHash(),g?(h=m.extractState(g||d.location.href,!0),h?m.replaceState(h.data,h.title,h.url,!1):(m.Adapter.trigger(a,"anchorchange"),m.busy(!1)),m.expectedStateId=!1,!1):(e=m.Adapter.extractEventData("state",b,c)||!1,e?f=m.getStateById(e):m.expectedStateId?f=m.getStateById(m.expectedStateId):f=m.extractState(d.location.href),f||(f=m.createStateObject(null,null,d.location.href)),m.expectedStateId=!1,m.isLastSavedState(f)?(m.busy(!1),!1):(m.storeState(f),m.saveState(f),m.setTitle(f),m.Adapter.trigger(a,"statechange"),m.busy(!1),!0))},m.Adapter.bind(a,"popstate",m.onPopState),m.pushState=function(b,c,d,e){if(m.getHashByUrl(d)&&m.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(e!==!1&&m.busy())return m.pushQueue({scope:m,callback:m.pushState,args:arguments,queue:e}),!1;m.busy(!0);var f=m.createStateObject(b,c,d);return m.isLastSavedState(f)?m.busy(!1):(m.storeState(f),m.expectedStateId=f.id,n.pushState(f.id,f.title,f.url),m.Adapter.trigger(a,"popstate")),!0},m.replaceState=function(b,c,d,e){if(m.getHashByUrl(d)&&m.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(e!==!1&&m.busy())return m.pushQueue({scope:m,callback:m.replaceState,args:arguments,queue:e}),!1;m.busy(!0);var f=m.createStateObject(b,c,d);return m.isLastSavedState(f)?m.busy(!1):(m.storeState(f),m.expectedStateId=f.id,n.replaceState(f.id,f.title,f.url),m.Adapter.trigger(a,"popstate")),!0};if(f){try{m.store=k.parse(f.getItem("History.store"))||{}}catch(p){m.store={}}m.normalizeStore()}else m.store={},m.normalizeStore();m.Adapter.bind(a,"beforeunload",m.clearAllIntervals),m.Adapter.bind(a,"unload",m.clearAllIntervals),m.saveState(m.storeState(m.extractState(d.location.href,!0))),f&&(m.onUnload=function(){var a,b;try{a=k.parse(f.getItem("History.store"))||{}}catch(c){a={}}a.idToState=a.idToState||{},a.urlToId=a.urlToId||{},a.stateToId=a.stateToId||{};for(b in m.idToState){if(!m.idToState.hasOwnProperty(b))continue;a.idToState[b]=m.idToState[b]}for(b in m.urlToId){if(!m.urlToId.hasOwnProperty(b))continue;a.urlToId[b]=m.urlToId[b]}for(b in m.stateToId){if(!m.stateToId.hasOwnProperty(b))continue;a.stateToId[b]=m.stateToId[b]}m.store=a,m.normalizeStore(),f.setItem("History.store",k.stringify(a))},m.intervalList.push(i(m.onUnload,m.options.storeInterval)),m.Adapter.bind(a,"beforeunload",m.onUnload),m.Adapter.bind(a,"unload",m.onUnload));if(!m.emulated.pushState){m.bugs.safariPoll&&m.intervalList.push(i(m.safariStatePoll,m.options.safariPollInterval));if(e.vendor==="Apple Computer, Inc."||(e.appCodeName||"")==="Mozilla")m.Adapter.bind(a,"hashchange",function(){m.Adapter.trigger(a,"popstate")}),m.getHash()&&m.Adapter.onDomLoad(function(){m.Adapter.trigger(a,"hashchange")})}},m.init()})(window) -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | 48 | 49 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 88 | 89 | 90 | 91 | 94 | 95 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 193 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/hammer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Hammer.JS 3 | * version 0.4 4 | * author: Eight Media 5 | * https://github.com/EightMedia/hammer.js 6 | */ 7 | function Hammer(element, options, undefined) 8 | { 9 | var self = this; 10 | 11 | var defaults = { 12 | // prevent the default event or not... might be buggy when false 13 | prevent_default : false, 14 | css_hacks : true, 15 | 16 | drag : true, 17 | drag_vertical : true, 18 | drag_horizontal : true, 19 | // minimum distance before the drag event starts 20 | drag_min_distance : 20, // pixels 21 | 22 | // pinch zoom and rotation 23 | transform : true, 24 | scale_treshold : 0.1, 25 | rotation_treshold : 15, // degrees 26 | 27 | tap : true, 28 | tap_double : true, 29 | tap_max_interval : 300, 30 | tap_double_distance: 20, 31 | 32 | hold : true, 33 | hold_timeout : 500 34 | }; 35 | options = mergeObject(defaults, options); 36 | 37 | // some css hacks 38 | (function() { 39 | if(!options.css_hacks) { 40 | return false; 41 | } 42 | 43 | var vendors = ['webkit','moz','ms','o','']; 44 | var css_props = { 45 | "userSelect": "none", 46 | "touchCallout": "none", 47 | "userDrag": "none", 48 | "tapHighlightColor": "rgba(0,0,0,0)" 49 | }; 50 | 51 | var prop = ''; 52 | for(var i = 0; i < vendors.length; i++) { 53 | for(var p in css_props) { 54 | prop = p; 55 | if(vendors[i]) { 56 | prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1); 57 | } 58 | element.style[ prop ] = css_props[p]; 59 | } 60 | } 61 | })(); 62 | 63 | // holds the distance that has been moved 64 | var _distance = 0; 65 | 66 | // holds the exact angle that has been moved 67 | var _angle = 0; 68 | 69 | // holds the diraction that has been moved 70 | var _direction = 0; 71 | 72 | // holds position movement for sliding 73 | var _pos = { }; 74 | 75 | // how many fingers are on the screen 76 | var _fingers = 0; 77 | 78 | var _first = false; 79 | 80 | var _gesture = null; 81 | var _prev_gesture = null; 82 | 83 | var _touch_start_time = null; 84 | var _prev_tap_pos = {x: 0, y: 0}; 85 | var _prev_tap_end_time = null; 86 | 87 | var _hold_timer = null; 88 | 89 | var _offset = {}; 90 | 91 | // keep track of the mouse status 92 | var _mousedown = false; 93 | 94 | var _event_start; 95 | var _event_move; 96 | var _event_end; 97 | 98 | 99 | /** 100 | * angle to direction define 101 | * @param float angle 102 | * @return string direction 103 | */ 104 | this.getDirectionFromAngle = function( angle ) 105 | { 106 | var directions = { 107 | down: angle >= 45 && angle < 135, //90 108 | left: angle >= 135 || angle <= -135, //180 109 | up: angle < -45 && angle > -135, //270 110 | right: angle >= -45 && angle <= 45 //0 111 | }; 112 | 113 | var direction, key; 114 | for(key in directions){ 115 | if(directions[key]){ 116 | direction = key; 117 | break; 118 | } 119 | } 120 | return direction; 121 | }; 122 | 123 | 124 | /** 125 | * count the number of fingers in the event 126 | * when no fingers are detected, one finger is returned (mouse pointer) 127 | * @param event 128 | * @return int fingers 129 | */ 130 | function countFingers( event ) 131 | { 132 | // there is a bug on android (until v4?) that touches is always 1, 133 | // so no multitouch is supported, e.g. no, zoom and rotation... 134 | return event.touches ? event.touches.length : 1; 135 | } 136 | 137 | 138 | /** 139 | * get the x and y positions from the event object 140 | * @param event 141 | * @return array [{ x: int, y: int }] 142 | */ 143 | function getXYfromEvent( event ) 144 | { 145 | event = event || window.event; 146 | 147 | // no touches, use the event pageX and pageY 148 | if(!event.touches) { 149 | var doc = document, 150 | body = doc.body; 151 | 152 | return [{ 153 | x: event.pageX || event.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && doc.clientLeft || 0 ), 154 | y: event.pageY || event.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && doc.clientTop || 0 ) 155 | }]; 156 | } 157 | // multitouch, return array with positions 158 | else { 159 | var pos = [], src; 160 | for(var t=0, len=event.touches.length; t options.drag_min_distance) || _gesture == 'drag') { 262 | // calculate the angle 263 | _angle = getAngle(_pos.start[0], _pos.move[0]); 264 | _direction = self.getDirectionFromAngle(_angle); 265 | 266 | // check the movement and stop if we go in the wrong direction 267 | var is_vertical = (_direction == 'up' || _direction == 'down'); 268 | if(((is_vertical && !options.drag_vertical) || (!is_vertical && !options.drag_horizontal)) 269 | && (_distance > options.drag_min_distance)) { 270 | return; 271 | } 272 | 273 | _gesture = 'drag'; 274 | 275 | var position = { x: _pos.move[0].x - _offset.left, 276 | y: _pos.move[0].y - _offset.top }; 277 | 278 | var event_obj = { 279 | originalEvent : event, 280 | position : position, 281 | direction : _direction, 282 | distance : _distance, 283 | distanceX : _distance_x, 284 | distanceY : _distance_y, 285 | angle : _angle 286 | }; 287 | 288 | // on the first time trigger the start event 289 | if(_first) { 290 | triggerEvent("dragstart", event_obj); 291 | 292 | _first = false; 293 | } 294 | 295 | // normal slide event 296 | triggerEvent("drag", event_obj); 297 | 298 | cancelEvent(event); 299 | } 300 | }, 301 | 302 | 303 | // transform gesture 304 | // fired on touchmove 305 | transform : function(event) 306 | { 307 | if(options.transform) { 308 | var scale = event.scale || 1; 309 | var rotation = event.rotation || 0; 310 | 311 | if(countFingers(event) != 2) { 312 | return false; 313 | } 314 | 315 | if(_gesture != 'drag' && 316 | (_gesture == 'transform' || Math.abs(1-scale) > options.scale_treshold 317 | || Math.abs(rotation) > options.rotation_treshold)) { 318 | _gesture = 'transform'; 319 | 320 | _pos.center = { x: ((_pos.move[0].x + _pos.move[1].x) / 2) - _offset.left, 321 | y: ((_pos.move[0].y + _pos.move[1].y) / 2) - _offset.top }; 322 | 323 | var event_obj = { 324 | originalEvent : event, 325 | position : _pos.center, 326 | scale : scale, 327 | rotation : rotation 328 | }; 329 | 330 | // on the first time trigger the start event 331 | if(_first) { 332 | triggerEvent("transformstart", event_obj); 333 | _first = false; 334 | } 335 | 336 | triggerEvent("transform", event_obj); 337 | 338 | cancelEvent(event); 339 | 340 | return true; 341 | } 342 | } 343 | 344 | return false; 345 | }, 346 | 347 | 348 | // tap and double tap gesture 349 | // fired on touchend 350 | tap : function(event) 351 | { 352 | // compare the kind of gesture by time 353 | var now = new Date().getTime(); 354 | var touch_time = now - _touch_start_time; 355 | 356 | // dont fire when hold is fired 357 | if(options.hold && !(options.hold && options.hold_timeout > touch_time)) { 358 | return; 359 | } 360 | 361 | // when previous event was tap and the tap was max_interval ms ago 362 | var is_double_tap = (function(){ 363 | if (_prev_tap_pos && options.tap_double && _prev_gesture == 'tap' && (_touch_start_time - _prev_tap_end_time) < options.tap_max_interval) { 364 | var x_distance = Math.abs(_prev_tap_pos[0].x - _pos.start[0].x); 365 | var y_distance = Math.abs(_prev_tap_pos[0].y - _pos.start[0].y); 366 | return (_prev_tap_pos && _pos.start && Math.max(x_distance, y_distance) < options.tap_double_distance); 367 | 368 | } 369 | return false; 370 | })(); 371 | 372 | if(is_double_tap) { 373 | _gesture = 'double_tap'; 374 | _prev_tap_end_time = null; 375 | 376 | triggerEvent("doubletap", { 377 | originalEvent : event, 378 | position : _pos.start 379 | }); 380 | cancelEvent(event); 381 | } 382 | 383 | // single tap is single touch 384 | else { 385 | _gesture = 'tap'; 386 | _prev_tap_end_time = now; 387 | _prev_tap_pos = _pos.start; 388 | 389 | if(options.tap) { 390 | triggerEvent("tap", { 391 | originalEvent : event, 392 | position : _pos.start 393 | }); 394 | cancelEvent(event); 395 | } 396 | } 397 | 398 | } 399 | 400 | }; 401 | 402 | 403 | function handleEvents(event) 404 | { 405 | switch(event.type) 406 | { 407 | case 'mousedown': 408 | case 'touchstart': 409 | _pos.start = getXYfromEvent(event); 410 | _touch_start_time = new Date().getTime(); 411 | _fingers = countFingers(event); 412 | _first = true; 413 | _event_start = event; 414 | 415 | // borrowed from jquery offset https://github.com/jquery/jquery/blob/master/src/offset.js 416 | var box = element.getBoundingClientRect(); 417 | var clientTop = element.clientTop || document.body.clientTop || 0; 418 | var clientLeft = element.clientLeft || document.body.clientLeft || 0; 419 | var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop; 420 | var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft; 421 | 422 | _offset = { 423 | top: box.top + scrollTop - clientTop, 424 | left: box.left + scrollLeft - clientLeft 425 | }; 426 | 427 | _mousedown = true; 428 | 429 | // hold gesture 430 | gestures.hold(event); 431 | 432 | if(options.prevent_default) { 433 | cancelEvent(event); 434 | } 435 | break; 436 | 437 | case 'mousemove': 438 | case 'touchmove': 439 | if(!_mousedown) { 440 | return false; 441 | } 442 | _event_move = event; 443 | _pos.move = getXYfromEvent(event); 444 | 445 | if(!gestures.transform(event)) { 446 | gestures.drag(event); 447 | } 448 | break; 449 | 450 | case 'mouseup': 451 | case 'mouseout': 452 | case 'touchcancel': 453 | case 'touchend': 454 | if(!_mousedown || (_gesture != 'transform' && event.touches && event.touches.length > 0)) { 455 | return false; 456 | } 457 | 458 | _mousedown = false; 459 | _event_end = event; 460 | 461 | // drag gesture 462 | // dragstart is triggered, so dragend is possible 463 | if(_gesture == 'drag') { 464 | triggerEvent("dragend", { 465 | originalEvent : event, 466 | direction : _direction, 467 | distance : _distance, 468 | angle : _angle 469 | }); 470 | } 471 | 472 | // transform 473 | // transformstart is triggered, so transformed is possible 474 | else if(_gesture == 'transform') { 475 | triggerEvent("transformend", { 476 | originalEvent : event, 477 | position : _pos.center, 478 | scale : event.scale, 479 | rotation : event.rotation 480 | }); 481 | } 482 | else { 483 | gestures.tap(_event_start); 484 | } 485 | 486 | _prev_gesture = _gesture; 487 | 488 | // reset vars 489 | reset(); 490 | break; 491 | } 492 | } 493 | 494 | 495 | // bind events for touch devices 496 | // except for windows phone 7.5, it doesnt support touch events..! 497 | if('ontouchstart' in window) { 498 | element.addEventListener("touchstart", handleEvents, false); 499 | element.addEventListener("touchmove", handleEvents, false); 500 | element.addEventListener("touchend", handleEvents, false); 501 | element.addEventListener("touchcancel", handleEvents, false); 502 | } 503 | // for non-touch 504 | else { 505 | 506 | if(element.addEventListener){ // prevent old IE errors 507 | element.addEventListener("mouseout", function(event) { 508 | if(!isInsideHammer(element, event.relatedTarget)) { 509 | handleEvents(event); 510 | } 511 | }, false); 512 | element.addEventListener("mouseup", handleEvents, false); 513 | element.addEventListener("mousedown", handleEvents, false); 514 | element.addEventListener("mousemove", handleEvents, false); 515 | 516 | // events for older IE 517 | }else if(document.attachEvent){ 518 | element.attachEvent("onmouseout", function(event) { 519 | if(!isInsideHammer(element, event.relatedTarget)) { 520 | handleEvents(event); 521 | } 522 | }, false); 523 | element.attachEvent("onmouseup", handleEvents); 524 | element.attachEvent("onmousedown", handleEvents); 525 | element.attachEvent("onmousemove", handleEvents); 526 | } 527 | } 528 | 529 | 530 | /** 531 | * find if element is (inside) given parent element 532 | * @param object element 533 | * @param object parent 534 | * @return bool inside 535 | */ 536 | function isInsideHammer(parent, child) { 537 | // get related target for IE 538 | if(!child && window.event && window.event.toElement){ 539 | child = window.event.toElement; 540 | } 541 | 542 | if(parent === child){ 543 | return true; 544 | } 545 | 546 | // loop over parentNodes of child until we find hammer element 547 | if(child){ 548 | var node = child.parentNode; 549 | while(node !== null){ 550 | if(node === parent){ 551 | return true; 552 | }; 553 | node = node.parentNode; 554 | } 555 | } 556 | return false; 557 | } 558 | 559 | 560 | /** 561 | * merge 2 objects into a new object 562 | * @param object obj1 563 | * @param object obj2 564 | * @return object merged object 565 | */ 566 | function mergeObject(obj1, obj2) { 567 | var output = {}; 568 | 569 | if(!obj2) { 570 | return obj1; 571 | } 572 | 573 | for (var prop in obj1) { 574 | if (prop in obj2) { 575 | output[prop] = obj2[prop]; 576 | } else { 577 | output[prop] = obj1[prop]; 578 | } 579 | } 580 | return output; 581 | } 582 | 583 | function isFunction( obj ){ 584 | return Object.prototype.toString.call( obj ) == "[object Function]"; 585 | } 586 | } -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/index.html: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | Podio: Going client-side on the web 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 |

35 |

36 |

37 |
38 |
39 | 40 | 41 |
42 |

Our team

43 |
44 |
45 | 46 | 47 |
48 | Description 49 |
50 |
51 | 52 | 53 |
54 |

Our principles

55 |
56 |
57 |
    58 |
  • Constantly evolve product and platform
  • 59 |
  • Deliver & fail fast
  • 60 |
  • Data-driven (A/B testing, measure, feedback)
  • 61 |
  • The right tools for the job
  • 62 |
  • Focus on value creation for our customers
  • 63 |
64 |
65 |
66 | 67 | 68 |
69 |

Evolution of our platform (while airbourne)

70 |
71 |
72 | Description 73 |
74 |
75 | 76 | 77 |
78 |

First prototype (2009)

79 |
80 |
81 | 82 | 83 |
84 |

Traditional website

85 |
86 |
87 | Description 88 |
89 |
90 | 91 | 92 |
93 |

Podio API (2010)

94 |
95 |
96 | 97 | 98 |
99 |

Central API

100 |
101 |
102 | Description 103 |
104 |
105 | 106 | 107 |
108 |

Project Zeus (2011)

109 |
110 |
111 | 112 | 113 |
114 | Description 115 |
116 |
117 | 118 | 119 |
120 |

Codename Hermes (2012)

121 |
122 |
123 | 124 | 125 |
126 |

Going client side.

127 |
128 |
129 | 130 | 131 |
132 |

Why going client side?

133 |
134 | 135 |
136 |

Product ambition.

137 |
138 |
139 | 140 | 141 |
142 |

Why going client side?

143 |
144 | 145 |
146 |

User experience.

147 |
148 |
149 | 150 | 151 |
152 |

Technology is here.

153 |
154 | 155 |
156 | Description 157 |
158 |
159 | 160 | 161 |
162 |

Client-side architecture distribution

163 |
164 | 165 |
166 | Description 167 |
168 |
169 | 170 | 171 |
172 |

New problem

173 |
174 | 175 |
176 |

Manage state in a good way.

177 |
178 |
179 | 180 | 181 |
182 |

Goals

183 |
184 | 185 |
186 |
    187 |
  • 188 | Faster and more responsive user experience 189 |
      190 |
    • Better preceived performance
    • 191 |
    192 |
    193 |
  • 194 |
  • 195 | Separation of concerns 196 |
      197 |
    • Decouple from the DOM
    • 198 |
    • Reuse of components
    • 199 |
    200 |
    201 |
  • 202 |
  • 203 | More reliability & less regression 204 |
      205 |
    • Unit and integration tests
    • 206 |
    • Faster development
    • 207 |
    208 |
    209 |
  • 210 |
211 |
212 |
213 | 214 | 215 |
216 |

Requirements

217 |
218 | 219 |
220 |
    221 |
  • 222 | Fit existing infrastructure. Hybrid. 223 |
      224 |
    • Live on top of existing front-end
    • 225 |
    • Same stack
    • 226 |
    • Lightweight
    • 227 |
    • Long lived
    • 228 |
    229 |
    230 |
  • 231 |
  • 232 | Simple to understand. 233 |
      234 |
    • Similar to Rails
    • 235 |
    • Productivity
    • 236 |
    • Onboarding
    • 237 |
    • Cross-codebase
    • 238 |
    239 |
    240 |
  • 241 |
242 |
243 |
244 | 245 | 246 |
247 | Description 248 |
249 |
250 | 251 | 252 |
253 |

Why Backbone?

254 |
255 |
256 |
    257 |
  • Many opinionated frameworks (JavaScript MVC, SproutCore, Knockout)
  • 258 |
  • Minimalistic and extensible (1500 lines)
  • 259 |
  • No lock-in into specific patterns/tools
  • 260 |
  • Fit our existing infrastructure
  • 261 |
262 |
263 |
264 | 265 | 266 |
267 |

Backbone introduction

268 |
269 |
270 |
    271 |
  • It's MV* - not MVC
  • 272 |
273 |
    274 |
  • Models
  • 275 |
  • Collections
  • 276 |
  • Views
  • 277 |
  • Routers
  • 278 |
279 |

And also:

280 |
    281 |
  • Easy inheritance
  • 282 |
  • Events (Pub/Sub) mixed into objects
  • 283 |
284 |
285 |
286 | 287 | 288 |
289 |

Backbone: Models

290 |
291 |
292 |
    293 |
  • Encapsulates data and domain logic
  • 294 |
  • Serializable to JSON
  • 295 |
  • RESTful data fetching, persistence and URL management built in
  • 296 |
  • Validation
  • 297 |
  • Fires events on changes
  • 298 |
299 |
300 |         var model = Backbone.Model.extend({
301 |           toggleLike: function() {
302 |             if (this.get('liked')) {
303 |               this.unlike();
304 |             } else {
305 |               this.like();
306 |             }
307 |           },
308 | 
309 |           like: function() {
310 |             this.set({ liked: true });
311 |           },
312 | 
313 |           unlike: function() {
314 |             this.set({ liked: false });
315 |           }
316 |         });
317 |       
318 |
319 |
320 | 321 | 322 |
323 |

Backbone: Collections

324 |
325 |
326 |
    327 |
  • Collection of models and operations
  • 328 |
  • Full range of methods from underscore.js built in
  • 329 |
  • Fires events on add/remove
  • 330 |
331 | 332 |
333 |   var collection = Backbone.Collection.extend({
334 |   
335 |     model: Podio.Models.Meeting,
336 |     url: '/backbone',
337 |   
338 |     getAllByProperty: function(propertyValue) {
339 |       return this.filter(function(model) {
340 |         return model.get('property') === propertyValue;
341 |       });
342 |     }
343 | 
344 |   });
345 |     
346 |
347 |
348 | 349 | 350 |
351 |

Backbone: Views

352 |
353 |
354 |
    355 |
  • Renders data using templates
  • 356 |
  • Reacts on DOM events
  • 357 |
358 |
359 | var ActionBarView = Backbone.View.extend({
360 |   tagName:  "li",
361 |   template: _.template($('#item-template').html()),
362 |   events: {
363 |     "click .toggle"   : "toggleDone",
364 |     "dblclick .view"  : "edit",
365 |   },
366 | 
367 |   initialize: function() {
368 |     this.model.on('change', this.render, this);
369 |     this.model.on('destroy', this.remove, this);
370 |   },
371 | 
372 |   render: function() {
373 |     this.$el.html(this.template(this.model.toJSON()));
374 |     this.$el.toggleClass('done', this.model.get('done'));
375 |     return this;
376 |   },
377 | 
378 |   edit: function() {
379 |     this.$el.addClass("editing");
380 |     this.input.focus();
381 |   }
382 | }
383 | 
384 | 385 |
386 |
387 | 388 | 389 |
390 |

Backbone: Router

391 |
392 |
393 |
    394 |
  • Triggers state changes
  • 395 |
  • Hashbangs OR pushState
  • 396 |
397 |
398 | 399 |
400 | var router = Backbone.PodioRouter.extend({
401 |   routes : {
402 |     "items/:pageNum:"  : { action: "index" }
403 |     },
404 | 
405 |    routesindex : function (pageNum) {
406 | 
407 |    }
408 | });
409 |     
410 |
411 | 412 | 413 |
414 |

Backbone:

415 |
416 | 417 | 422 |
423 | 424 | 425 |
426 |

Our learnings.

427 |
428 |
429 | 430 | 431 |
432 |

Backbone event flow

433 |
434 |
435 | Description 436 |
437 |
438 | 439 | 440 |
441 |

Limitations of MV* Frameworks

442 |
443 |
444 |
    445 |
  • Tight binding between Views and Models does not scale
  • 446 |
  • Separate data updates from actions
  • 447 |
  • Sharing models across components is not a good idea
  • 448 |
  • Views are context specific
  • 449 |
  • We want to return multiple models at once
  • 450 |
451 |
452 |
453 | 454 | 455 |
456 |

Our extensions for Backbone

457 |
458 |
459 |
    460 |
  • Controllers & Event Bus
  • 461 |
  • Hybrid routing
  • 462 |
  • Model relations
  • 463 |
  • Rendering and view helpers
  • 464 |
  • Better class inherientance
  • 465 |
466 |
467 |
468 | 469 | 470 |
471 |

Podio event flow

472 |
473 |
474 | Description 475 |
476 |
477 | 478 | 479 |
480 |

The controller

481 |
482 |
483 | Description 484 |
485 |
486 | 487 | 488 |
489 |

A single component

490 |
491 |
492 | Description 493 |
494 |
495 | 496 | 497 |
498 |

Podio event flow

499 |
500 |
501 | Description 502 |
503 |
504 | 505 | 506 |
507 |

Controllers

508 |
509 |
510 |
    511 |
  • Decoupling Views and Models
  • 512 |
  • Single point of responsibility (top-down actions only)
  • 513 |
  • Views are generic, Controllers are context-aware
  • 514 |
  • Controllers manage components and the global state
  • 515 |
  • Subcontrollers when necessary
  • 516 |
517 |
518 |
519 | 520 | 521 |
522 |

Controllers

523 |
524 |
525 |
526 | var calendarsController = Backbone.PodioController.extend({
527 |   bindEvents: function() {
528 |     this.eventBus.bind('componentOne:addService', this.onServiceAdded, this);
529 |   },
530 | 
531 |   initialize: function () {
532 |     this.eventBus = _.extend({}, Backbone.Events);
533 |     this.bindEvents();
534 | 
535 |     this.componentOne = new ComponentOne({ eventBus: this.eventBus });
536 |   },
537 | 
538 |   onServiceAdded: function() {
539 |     this.componentOne.triggerSomeBehavior();
540 |   }
541 | });
542 |       
543 |
544 |
545 | 546 | 547 |
548 |

Event Bus

549 |
550 |
551 |
    552 |
  • All components are attached to one bus and signal their specific events
  • 553 |
  • Only controllers listen on the bus and act depending on their context and current state
  • 554 |
555 |
556 | var componentOne = Backbone.PodioView.extend({
557 |   events: {
558 |     'click .trigger': 'onTriggerClick'
559 |   },
560 | 
561 |   onTriggerClick: function() {
562 |     this.trigger('componentOne:addService');
563 |   }
564 | });
565 |       
566 |
567 |
568 | 569 | 570 | 571 |
572 |

View simplifications

573 |
574 |
575 |
576 | 
577 | define('views/Podio.Views.ActionBar', function (require) {
578 | 
579 |   return Backbone.PodioView.extend({
580 | 
581 |     initialize: function(options) {
582 |       this.appId = options.appId;
583 |       this._super();
584 |     },
585 | 
586 |     podioEvents: {
587 |       'click .action-bar .like' : 'onActionLikeClicked'
588 |     },
589 | 
590 |     shortcuts: {
591 |       'l' : 'onShortcutLikePressed',
592 |     },
593 | 
594 |     onActionLikeClicked: function(elmTarget, e) {
595 |       this.trigger('actionBar:likeTriggered', this.appId );
596 |     }
597 |   });
598 | 
599 | })
600 | 
601 | 
602 |
603 |
604 | 605 | 606 |
607 |

Templates and view helpers

608 |
609 |
610 |
    611 |
  • Same helpers as in Rails make transition easy and developers happy
  • 612 |
  • Underscore's templating system is used which is minimalistic and compatible with Rails ERB syntax
  • 613 |
614 | 615 |
616 |       ...
617 |       <div class="footer">
618 |         <%- button(t('Done #filefinder'), '', { 'color': 'green', 'tabindex' : '3' }) %>
619 |         <%- button(t('Cancel #filefinder'), '', { 'color': 'silver', 'class':'align-right' }) %>
620 |       </div>
621 |       ...
622 |     
623 | 624 |
625 |
626 | 627 | 628 | 632 | 633 | 634 | 635 |
636 |

Testing.

637 |
638 |
639 | 640 | 641 |
642 |

Unit testing

643 |
644 |
645 |
    646 |
  • Jasmine as a test suite
  • 647 |
  • Sinon.js as a mocking framework
  • 648 |
  • Using Evergreen gem to run tests headlessly (capybara-webkit) and in the browser
  • 649 |
650 | 651 |
652 | it("function is called once", function () {
653 |   var func = sinon.mock(myObject);
654 |   func.expects("myFunction").once().returnsArg(0);
655 | 
656 |   myObject.myFunction();
657 | 
658 |   func.verify();
659 | });
660 |       
661 |
662 |
663 | 664 | 665 |
666 |

Acceptance testing

667 |
668 |
669 | Description 670 |
671 |
672 | 673 | 674 | 675 |
676 |

Auto-DT

677 |
678 |
679 |
    680 |
  • Automated browser testing
  • 681 |
  • Began with Selenium & Capybara
  • 682 |
  • Tests written in Ruby
  • 683 |
  • Went headless with PhantomJS
  • 684 |
685 |
686 |
687 | 688 | 689 |
690 |

Auto-DT: Example

691 |
692 |
693 |
694 | def test_add_more_than_10_users_to_employee_network
695 |     login_as(:user => :leela, :org => :planet_express) do |current_user, org|
696 |       visit("#{@org.url}employeenetwork/invite")
697 | 
698 |       # Invite twelve users
699 |       with PodioPicker do |w|
700 |         12.times do |count|
701 |           invited_user_email = "user#{count}@#{org.domains.first}"
702 |           w.add_token('#simple_invitation_box', invited_user_email)
703 |         end
704 |       end
705 | 
706 |       # Send invitations
707 |       find('#invite_button').click
708 | 
709 |       # Invite completed
710 |       assert_path('/employeenetwork')
711 |     end
712 |   end
713 |       
714 |
715 |
716 | 717 | 718 |
719 |

Going forward.

720 |
721 |
722 | 723 | 724 |
725 |

Real-time experience.

726 |
727 |
728 | 729 | 730 |
731 |

More automation.

732 |
733 |
734 | 735 | 736 |
737 | Description 738 |

Future is now.

739 |
740 |
741 | 742 | 743 |
744 |

Thanks.

745 |
746 |

747 | 748 |

749 |
750 | 751 | 752 |
753 | 754 | 755 | 756 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/prettify/lang-xq.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/], 2 | ["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/], 3 | ["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]); 4 | -------------------------------------------------------------------------------- /citrix-tech-group-podio-frontend-client-side/js/slide-deck.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @authors Luke Mahe 3 | * @authors Eric Bidelman 4 | * @fileoverview TODO 5 | */ 6 | document.cancelFullScreen = document.webkitCancelFullScreen || 7 | document.mozCancelFullScreen; 8 | 9 | /** 10 | * @constructor 11 | */ 12 | function SlideDeck(el) { 13 | this.curSlide_ = 0; 14 | this.prevSlide_ = 0; 15 | this.config_ = null; 16 | this.container = el || document.querySelector('slides'); 17 | this.slides = []; 18 | this.controller = null; 19 | 20 | this.getCurrentSlideFromHash_(); 21 | 22 | // Call this explicitly. Modernizr.load won't be done until after DOM load. 23 | this.onDomLoaded_.bind(this)(); 24 | } 25 | 26 | /** 27 | * @const 28 | * @private 29 | */ 30 | SlideDeck.prototype.SLIDE_CLASSES_ = [ 31 | 'far-past', 'past', 'current', 'next', 'far-next']; 32 | 33 | /** 34 | * @const 35 | * @private 36 | */ 37 | SlideDeck.prototype.CSS_DIR_ = 'theme/css/'; 38 | 39 | /** 40 | * @private 41 | */ 42 | SlideDeck.prototype.getCurrentSlideFromHash_ = function() { 43 | var slideNo = parseInt(document.location.hash.substr(1)); 44 | 45 | if (slideNo) { 46 | this.curSlide_ = slideNo - 1; 47 | } else { 48 | this.curSlide_ = 0; 49 | } 50 | }; 51 | 52 | /** 53 | * @param {number} slideNo 54 | */ 55 | SlideDeck.prototype.loadSlide = function(slideNo) { 56 | if (slideNo) { 57 | this.curSlide_ = slideNo - 1; 58 | this.updateSlides_(); 59 | } 60 | }; 61 | 62 | /** 63 | * @private 64 | */ 65 | SlideDeck.prototype.onDomLoaded_ = function(e) { 66 | document.body.classList.add('loaded'); // Add loaded class for templates to use. 67 | 68 | this.slides = this.container.querySelectorAll('slide:not([hidden]):not(.backdrop)'); 69 | 70 | // If we're on a smartphone, apply special sauce. 71 | if (Modernizr.mq('only screen and (max-device-width: 480px)')) { 72 | // var style = document.createElement('link'); 73 | // style.rel = 'stylesheet'; 74 | // style.type = 'text/css'; 75 | // style.href = this.CSS_DIR_ + 'phone.css'; 76 | // document.querySelector('head').appendChild(style); 77 | 78 | // No need for widescreen layout on a phone. 79 | this.container.classList.remove('layout-widescreen'); 80 | } 81 | 82 | this.loadConfig_(SLIDE_CONFIG); 83 | this.addEventListeners_(); 84 | this.updateSlides_(); 85 | 86 | // Add slide numbers and total slide count metadata to each slide. 87 | var that = this; 88 | for (var i = 0, slide; slide = this.slides[i]; ++i) { 89 | slide.dataset.slideNum = i + 1; 90 | slide.dataset.totalSlides = this.slides.length; 91 | 92 | slide.addEventListener('click', function(e) { 93 | if (document.body.classList.contains('overview')) { 94 | that.loadSlide(this.dataset.slideNum); 95 | e.preventDefault(); 96 | window.setTimeout(function() { 97 | that.toggleOverview(); 98 | }, 500); 99 | } 100 | }, false); 101 | } 102 | 103 | // Note: this needs to come after addEventListeners_(), which adds a 104 | // 'keydown' listener that this controller relies on. 105 | // Also, no need to set this up if we're on mobile. 106 | if (!Modernizr.touch) { 107 | this.controller = new SlideController(this); 108 | if (this.controller.isPopup) { 109 | document.body.classList.add('popup'); 110 | } 111 | } 112 | }; 113 | 114 | /** 115 | * @private 116 | */ 117 | SlideDeck.prototype.addEventListeners_ = function() { 118 | document.addEventListener('keydown', this.onBodyKeyDown_.bind(this), false); 119 | window.addEventListener('popstate', this.onPopState_.bind(this), false); 120 | 121 | // var transEndEventNames = { 122 | // 'WebkitTransition': 'webkitTransitionEnd', 123 | // 'MozTransition': 'transitionend', 124 | // 'OTransition': 'oTransitionEnd', 125 | // 'msTransition': 'MSTransitionEnd', 126 | // 'transition': 'transitionend' 127 | // }; 128 | // 129 | // // Find the correct transitionEnd vendor prefix. 130 | // window.transEndEventName = transEndEventNames[ 131 | // Modernizr.prefixed('transition')]; 132 | // 133 | // // When slides are done transitioning, kickoff loading iframes. 134 | // // Note: we're only looking at a single transition (on the slide). This 135 | // // doesn't include autobuilds the slides may have. Also, if the slide 136 | // // transitions on multiple properties (e.g. not just 'all'), this doesn't 137 | // // handle that case. 138 | // this.container.addEventListener(transEndEventName, function(e) { 139 | // this.enableSlideFrames_(this.curSlide_); 140 | // }.bind(this), false); 141 | 142 | // document.addEventListener('slideenter', function(e) { 143 | // var slide = e.target; 144 | // window.setTimeout(function() { 145 | // this.enableSlideFrames_(e.slideNumber); 146 | // this.enableSlideFrames_(e.slideNumber + 1); 147 | // }.bind(this), 300); 148 | // }.bind(this), false); 149 | }; 150 | 151 | /** 152 | * @private 153 | * @param {Event} e The pop event. 154 | */ 155 | SlideDeck.prototype.onPopState_ = function(e) { 156 | if (e.state != null) { 157 | this.curSlide_ = e.state; 158 | this.updateSlides_(true); 159 | } 160 | }; 161 | 162 | /** 163 | * @param {Event} e 164 | */ 165 | SlideDeck.prototype.onBodyKeyDown_ = function(e) { 166 | if (/^(input|textarea)$/i.test(e.target.nodeName) || 167 | e.target.isContentEditable) { 168 | return; 169 | } 170 | 171 | // Forward keydowns to the main slides if we're the popup. 172 | if (this.controller && this.controller.isPopup) { 173 | this.controller.sendMsg({keyCode: e.keyCode}); 174 | } 175 | 176 | console.log('key', e.keyCode); 177 | 178 | switch (e.keyCode) { 179 | case 13: // Enter 180 | if (document.body.classList.contains('overview')) { 181 | this.toggleOverview(); 182 | } 183 | break; 184 | 185 | case 39: // right arrow 186 | case 32: // space 187 | case 34: // PgDn 188 | this.nextSlide(); 189 | e.preventDefault(); 190 | break; 191 | 192 | case 37: // left arrow 193 | case 8: // Backspace 194 | case 33: // PgUp 195 | this.prevSlide(); 196 | e.preventDefault(); 197 | break; 198 | 199 | case 40: // down arrow 200 | this.nextSlide(); 201 | e.preventDefault(); 202 | break; 203 | 204 | case 38: // up arrow 205 | this.prevSlide(); 206 | e.preventDefault(); 207 | break; 208 | 209 | case 72: // H: Toggle code highlighting 210 | document.body.classList.toggle('highlight-code'); 211 | break; 212 | 213 | case 79: // O: Toggle overview 214 | this.toggleOverview(); 215 | break; 216 | 217 | case 80: // P 218 | if (this.controller && this.controller.isPopup) { 219 | document.body.classList.toggle('with-notes'); 220 | } else if (this.controller && !this.controller.popup) { 221 | document.body.classList.toggle('with-notes'); 222 | } 223 | break; 224 | 225 | case 82: // R 226 | // TODO: implement refresh on main slides when popup is refreshed. 227 | break; 228 | 229 | case 27: // ESC: Hide notes and highlighting 230 | document.body.classList.remove('with-notes'); 231 | document.body.classList.remove('highlight-code'); 232 | 233 | if (document.body.classList.contains('overview')) { 234 | this.toggleOverview(); 235 | } 236 | break; 237 | 238 | case 70: // F: Toggle fullscreen 239 | // Only respect 'f' on body. Don't want to capture keys from an . 240 | // Also, ignore browser's fullscreen shortcut (cmd+shift+f) so we don't 241 | // get trapped in fullscreen! 242 | if (e.target == document.body && !(e.shiftKey && e.metaKey)) { 243 | if (document.mozFullScreen !== undefined && !document.mozFullScreen) { 244 | document.body.mozRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); 245 | } else if (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen) { 246 | document.body.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); 247 | } else { 248 | document.cancelFullScreen(); 249 | } 250 | } 251 | break; 252 | 253 | case 87: // W: Toggle widescreen 254 | // Only respect 'w' on body. Don't want to capture keys from an . 255 | if (e.target == document.body && !(e.shiftKey && e.metaKey)) { 256 | this.container.classList.toggle('layout-widescreen'); 257 | } 258 | break; 259 | } 260 | }; 261 | 262 | /** 263 | * 264 | */ 265 | SlideDeck.prototype.focusOverview_ = function() { 266 | var overview = document.body.classList.contains('overview'); 267 | 268 | for (var i = 0, slide; slide = this.slides[i]; i++) { 269 | slide.style[Modernizr.prefixed('transform')] = overview ? 270 | 'translateZ(-2500px) translate(' + (( i - this.curSlide_ ) * 105) + 271 | '%, 0%)' : ''; 272 | } 273 | }; 274 | 275 | /** 276 | */ 277 | SlideDeck.prototype.toggleOverview = function() { 278 | document.body.classList.toggle('overview'); 279 | 280 | this.focusOverview_(); 281 | }; 282 | 283 | /** 284 | * @private 285 | */ 286 | SlideDeck.prototype.loadConfig_ = function(config) { 287 | if (!config) { 288 | return; 289 | } 290 | 291 | this.config_ = config; 292 | 293 | var settings = this.config_.settings; 294 | 295 | this.loadTheme_(settings.theme || []); 296 | 297 | if (settings.favIcon) { 298 | this.addFavIcon_(settings.favIcon); 299 | } 300 | 301 | // Prettyprint. Default to on. 302 | if (!!!('usePrettify' in settings) || settings.usePrettify) { 303 | prettyPrint(); 304 | } 305 | 306 | if (settings.analytics) { 307 | this.loadAnalytics_(); 308 | } 309 | 310 | if (settings.fonts) { 311 | this.addFonts_(settings.fonts); 312 | } 313 | 314 | // Builds. Default to on. 315 | if (!!!('useBuilds' in settings) || settings.useBuilds) { 316 | this.makeBuildLists_(); 317 | } 318 | 319 | if (settings.title) { 320 | document.title = settings.title.replace(//, ' ') + ' - Google IO 2012'; 321 | document.querySelector('[data-config-title]').innerHTML = settings.title; 322 | } 323 | 324 | if (settings.subtitle) { 325 | document.querySelector('[data-config-subtitle]').innerHTML = settings.subtitle; 326 | } 327 | 328 | if (this.config_.presenters) { 329 | var presenters = this.config_.presenters; 330 | var dataConfigContact = document.querySelector('[data-config-contact]'); 331 | 332 | var html = []; 333 | if (presenters.length == 1) { 334 | var p = presenters[0]; 335 | 336 | html = [p.name, p.company].join('
'); 337 | 338 | var gplus = p.gplus ? 'g+' + p.gplus.replace(/https?:\/\//, '') + '' : ''; 340 | 341 | var twitter = p.twitter ? 'twitter' + 342 | '' + 343 | p.twitter + '' : ''; 344 | 345 | var www = p.www ? 'www' + p.www.replace(/https?:\/\//, '') + '' : ''; 347 | 348 | var github = p.github ? 'github' + p.github.replace(/https?:\/\//, '') + '' : ''; 350 | 351 | var html2 = [gplus, twitter, www, github].join('
'); 352 | 353 | if (dataConfigContact) { 354 | dataConfigContact.innerHTML = html2; 355 | } 356 | } else { 357 | for (var i = 0, p; p = presenters[i]; ++i) { 358 | html.push(p.name + ' - ' + p.company); 359 | } 360 | html = html.join('
'); 361 | if (dataConfigContact) { 362 | dataConfigContact.innerHTML = html; 363 | } 364 | } 365 | 366 | var dataConfigPresenter = document.querySelector('[data-config-presenter]'); 367 | if (dataConfigPresenter) { 368 | document.querySelector('[data-config-presenter]').innerHTML = html; 369 | } 370 | } 371 | 372 | /* Left/Right tap areas. Default to including. */ 373 | if (!!!('enableSlideAreas' in settings) || settings.enableSlideAreas) { 374 | var el = document.createElement('div'); 375 | el.classList.add('slide-area'); 376 | el.id = 'prev-slide-area'; 377 | el.addEventListener('click', this.prevSlide.bind(this), false); 378 | this.container.appendChild(el); 379 | 380 | var el = document.createElement('div'); 381 | el.classList.add('slide-area'); 382 | el.id = 'next-slide-area'; 383 | el.addEventListener('click', this.nextSlide.bind(this), false); 384 | this.container.appendChild(el); 385 | } 386 | 387 | if (Modernizr.touch && (!!!('enableTouch' in settings) || 388 | settings.enableTouch)) { 389 | var self = this; 390 | 391 | // Note: this prevents mobile zoom in/out but prevents iOS from doing 392 | // it's crazy scroll over effect and disaligning the slides. 393 | window.addEventListener('touchstart', function(e) { 394 | e.preventDefault(); 395 | }, false); 396 | 397 | var hammer = new Hammer(this.container); 398 | hammer.ondragend = function(e) { 399 | if (e.direction == 'right' || e.direction == 'down') { 400 | self.prevSlide(); 401 | } else if (e.direction == 'left' || e.direction == 'up') { 402 | self.nextSlide(); 403 | } 404 | }; 405 | } 406 | }; 407 | 408 | /** 409 | * @private 410 | * @param {Array.} fonts 411 | */ 412 | SlideDeck.prototype.addFonts_ = function(fonts) { 413 | var el = document.createElement('link'); 414 | el.rel = 'stylesheet'; 415 | el.href = ('https:' == document.location.protocol ? 'https' : 'http') + 416 | '://fonts.googleapis.com/css?family=' + fonts.join('|') + '&v2'; 417 | document.querySelector('head').appendChild(el); 418 | }; 419 | 420 | /** 421 | * @private 422 | */ 423 | SlideDeck.prototype.buildNextItem_ = function() { 424 | var slide = this.slides[this.curSlide_]; 425 | var toBuild = slide.querySelector('.to-build'); 426 | var built = slide.querySelector('.build-current'); 427 | 428 | if (built) { 429 | built.classList.remove('build-current'); 430 | if (built.classList.contains('fade')) { 431 | built.classList.add('build-fade'); 432 | } 433 | } 434 | 435 | if (!toBuild) { 436 | var items = slide.querySelectorAll('.build-fade'); 437 | for (var j = 0, item; item = items[j]; j++) { 438 | item.classList.remove('build-fade'); 439 | } 440 | return false; 441 | } 442 | 443 | toBuild.classList.remove('to-build'); 444 | toBuild.classList.add('build-current'); 445 | 446 | return true; 447 | }; 448 | 449 | /** 450 | * @param {boolean=} opt_dontPush 451 | */ 452 | SlideDeck.prototype.prevSlide = function(opt_dontPush) { 453 | if (this.curSlide_ > 0) { 454 | var bodyClassList = document.body.classList; 455 | bodyClassList.remove('highlight-code'); 456 | 457 | // Toggle off speaker notes if they're showing when we move backwards on the 458 | // main slides. If we're the speaker notes popup, leave them up. 459 | if (this.controller && !this.controller.isPopup) { 460 | bodyClassList.remove('with-notes'); 461 | } else if (!this.controller) { 462 | bodyClassList.remove('with-notes'); 463 | } 464 | 465 | this.prevSlide_ = this.curSlide_--; 466 | 467 | this.updateSlides_(opt_dontPush); 468 | } 469 | }; 470 | 471 | /** 472 | * @param {boolean=} opt_dontPush 473 | */ 474 | SlideDeck.prototype.nextSlide = function(opt_dontPush) { 475 | if (!document.body.classList.contains('overview') && this.buildNextItem_()) { 476 | return; 477 | } 478 | 479 | if (this.curSlide_ < this.slides.length - 1) { 480 | var bodyClassList = document.body.classList; 481 | bodyClassList.remove('highlight-code'); 482 | 483 | // Toggle off speaker notes if they're showing when we advanced on the main 484 | // slides. If we're the speaker notes popup, leave them up. 485 | if (this.controller && !this.controller.isPopup) { 486 | bodyClassList.remove('with-notes'); 487 | } else if (!this.controller) { 488 | bodyClassList.remove('with-notes'); 489 | } 490 | 491 | this.prevSlide_ = this.curSlide_++; 492 | 493 | this.updateSlides_(opt_dontPush); 494 | } 495 | }; 496 | 497 | /* Slide events */ 498 | 499 | /** 500 | * Triggered when a slide enter/leave event should be dispatched. 501 | * 502 | * @param {string} type The type of event to trigger 503 | * (e.g. 'slideenter', 'slideleave'). 504 | * @param {number} slideNo The index of the slide that is being left. 505 | */ 506 | SlideDeck.prototype.triggerSlideEvent = function(type, slideNo) { 507 | var el = this.getSlideEl_(slideNo); 508 | if (!el) { 509 | return; 510 | } 511 | 512 | // Call onslideenter/onslideleave if the attribute is defined on this slide. 513 | var func = el.getAttribute(type); 514 | if (func) { 515 | new Function(func).call(el); // TODO: Don't use new Function() :( 516 | } 517 | 518 | // Dispatch event to listeners setup using addEventListener. 519 | var evt = document.createEvent('Event'); 520 | evt.initEvent(type, true, true); 521 | evt.slideNumber = slideNo + 1; // Make it readable 522 | evt.slide = el; 523 | 524 | el.dispatchEvent(evt); 525 | }; 526 | 527 | /** 528 | * @private 529 | */ 530 | SlideDeck.prototype.updateSlides_ = function(opt_dontPush) { 531 | var dontPush = opt_dontPush || false; 532 | 533 | var curSlide = this.curSlide_; 534 | for (var i = 0; i < this.slides.length; ++i) { 535 | switch (i) { 536 | case curSlide - 2: 537 | this.updateSlideClass_(i, 'far-past'); 538 | break; 539 | case curSlide - 1: 540 | this.updateSlideClass_(i, 'past'); 541 | break; 542 | case curSlide: 543 | this.updateSlideClass_(i, 'current'); 544 | break; 545 | case curSlide + 1: 546 | this.updateSlideClass_(i, 'next'); 547 | break; 548 | case curSlide + 2: 549 | this.updateSlideClass_(i, 'far-next'); 550 | break; 551 | default: 552 | this.updateSlideClass_(i); 553 | break; 554 | } 555 | }; 556 | 557 | this.triggerSlideEvent('slideleave', this.prevSlide_); 558 | this.triggerSlideEvent('slideenter', curSlide); 559 | 560 | // window.setTimeout(this.disableSlideFrames_.bind(this, curSlide - 2), 301); 561 | // 562 | // this.enableSlideFrames_(curSlide - 1); // Previous slide. 563 | // this.enableSlideFrames_(curSlide + 1); // Current slide. 564 | // this.enableSlideFrames_(curSlide + 2); // Next slide. 565 | 566 | // Enable current slide's iframes (needed for page loat at current slide). 567 | this.enableSlideFrames_(curSlide + 1); 568 | 569 | // No way to tell when all slide transitions + auto builds are done. 570 | // Give ourselves a good buffer to preload the next slide's iframes. 571 | window.setTimeout(this.enableSlideFrames_.bind(this, curSlide + 2), 1000); 572 | 573 | this.updateHash_(dontPush); 574 | 575 | if (document.body.classList.contains('overview')) { 576 | this.focusOverview_(); 577 | return; 578 | } 579 | 580 | }; 581 | 582 | /** 583 | * @private 584 | * @param {number} slideNo 585 | */ 586 | SlideDeck.prototype.enableSlideFrames_ = function(slideNo) { 587 | var el = this.slides[slideNo - 1]; 588 | if (!el) { 589 | return; 590 | } 591 | 592 | var frames = el.querySelectorAll('iframe'); 593 | for (var i = 0, frame; frame = frames[i]; i++) { 594 | this.enableFrame_(frame); 595 | } 596 | }; 597 | 598 | /** 599 | * @private 600 | * @param {number} slideNo 601 | */ 602 | SlideDeck.prototype.enableFrame_ = function(frame) { 603 | var src = frame.dataset.src; 604 | if (src && frame.src != src) { 605 | frame.src = src; 606 | } 607 | }; 608 | 609 | /** 610 | * @private 611 | * @param {number} slideNo 612 | */ 613 | SlideDeck.prototype.disableSlideFrames_ = function(slideNo) { 614 | var el = this.slides[slideNo - 1]; 615 | if (!el) { 616 | return; 617 | } 618 | 619 | var frames = el.querySelectorAll('iframe'); 620 | for (var i = 0, frame; frame = frames[i]; i++) { 621 | this.disableFrame_(frame); 622 | } 623 | }; 624 | 625 | /** 626 | * @private 627 | * @param {Node} frame 628 | */ 629 | SlideDeck.prototype.disableFrame_ = function(frame) { 630 | frame.src = 'about:blank'; 631 | }; 632 | 633 | /** 634 | * @private 635 | * @param {number} slideNo 636 | */ 637 | SlideDeck.prototype.getSlideEl_ = function(no) { 638 | if ((no < 0) || (no >= this.slides.length)) { 639 | return null; 640 | } else { 641 | return this.slides[no]; 642 | } 643 | }; 644 | 645 | /** 646 | * @private 647 | * @param {number} slideNo 648 | * @param {string} className 649 | */ 650 | SlideDeck.prototype.updateSlideClass_ = function(slideNo, className) { 651 | var el = this.getSlideEl_(slideNo); 652 | 653 | if (!el) { 654 | return; 655 | } 656 | 657 | if (className) { 658 | el.classList.add(className); 659 | } 660 | 661 | for (var i = 0, slideClass; slideClass = this.SLIDE_CLASSES_[i]; ++i) { 662 | if (className != slideClass) { 663 | el.classList.remove(slideClass); 664 | } 665 | } 666 | }; 667 | 668 | /** 669 | * @private 670 | */ 671 | SlideDeck.prototype.makeBuildLists_ = function () { 672 | for (var i = this.curSlide_, slide; slide = this.slides[i]; ++i) { 673 | var items = slide.querySelectorAll('.build > *'); 674 | for (var j = 0, item; item = items[j]; ++j) { 675 | if (item.classList) { 676 | item.classList.add('to-build'); 677 | if (item.parentNode.classList.contains('fade')) { 678 | item.classList.add('fade'); 679 | } 680 | } 681 | } 682 | } 683 | }; 684 | 685 | /** 686 | * @private 687 | * @param {boolean} dontPush 688 | */ 689 | SlideDeck.prototype.updateHash_ = function(dontPush) { 690 | if (!dontPush) { 691 | var slideNo = this.curSlide_ + 1; 692 | var hash = '#' + slideNo; 693 | if (window.history.pushState) { 694 | window.history.pushState(this.curSlide_, 'Slide ' + slideNo, hash); 695 | } else { 696 | window.location.replace(hash); 697 | } 698 | 699 | // Record GA hit on this slide. 700 | window['_gaq'] && window['_gaq'].push(['_trackPageview', 701 | document.location.href]); 702 | } 703 | }; 704 | 705 | 706 | /** 707 | * @private 708 | * @param {string} favIcon 709 | */ 710 | SlideDeck.prototype.addFavIcon_ = function(favIcon) { 711 | var el = document.createElement('link'); 712 | el.rel = 'icon'; 713 | el.type = 'image/png'; 714 | el.href = favIcon; 715 | document.querySelector('head').appendChild(el); 716 | }; 717 | 718 | /** 719 | * @private 720 | * @param {string} theme 721 | */ 722 | SlideDeck.prototype.loadTheme_ = function(theme) { 723 | var styles = []; 724 | if (theme.constructor.name === 'String') { 725 | styles.push(theme); 726 | } else { 727 | styles = theme; 728 | } 729 | 730 | for (var i = 0, style; themeUrl = styles[i]; i++) { 731 | var style = document.createElement('link'); 732 | style.rel = 'stylesheet'; 733 | style.type = 'text/css'; 734 | if (themeUrl.indexOf('http') == -1) { 735 | style.href = this.CSS_DIR_ + themeUrl + '.css'; 736 | } else { 737 | style.href = themeUrl; 738 | } 739 | document.querySelector('head').appendChild(style); 740 | } 741 | }; 742 | 743 | /** 744 | * @private 745 | */ 746 | SlideDeck.prototype.loadAnalytics_ = function() { 747 | var _gaq = window['_gaq'] || []; 748 | _gaq.push(['_setAccount', this.config_.settings.analytics]); 749 | _gaq.push(['_trackPageview']); 750 | 751 | (function() { 752 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 753 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 754 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 755 | })(); 756 | }; 757 | 758 | 759 | // Polyfill missing APIs (if we need to), then create the slide deck. 760 | // iOS < 5 needs classList, dataset, and window.matchMedia. Modernizr contains 761 | // the last one. 762 | (function() { 763 | Modernizr.load({ 764 | test: !!document.body.classList && !!document.body.dataset, 765 | nope: ['js/polyfills/classList.min.js', 'js/polyfills/dataset.min.js'], 766 | complete: function() { 767 | window.slidedeck = new SlideDeck(); 768 | } 769 | }); 770 | })(); 771 | --------------------------------------------------------------------------------