<commit_before>/*
 * Copyright (C) 2015 Glyptodon LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * A directive which displays the contents of a filesystem received through the
 * Guacamole client.
 */
angular.module('client').directive('guacFileBrowser', [function guacFileBrowser() {

    return {
        restrict: 'E',
        replace: true,
        scope: {

            /**
             * The client whose file transfers should be managed by this
             * directive.
             *
             * @type ManagedClient
             */
            client : '=',

            /**
             * @type ManagedFilesystem
             */
            filesystem : '='

        },

        templateUrl: 'app/client/templates/guacFileBrowser.html',
        controller: ['$scope', '$element', '$injector', function guacFileBrowserController($scope, $element, $injector) {

            // Required types
            var ManagedFilesystem = $injector.get('ManagedFilesystem');

            // Required services
            var $interpolate     = $injector.get('$interpolate');
            var $templateRequest = $injector.get('$templateRequest');

            /**
             * The jQuery-wrapped element representing the contents of the
             * current directory within the file browser.
             *
             * @type Element[]
             */
            var currentDirectoryContents = $element.find('.current-directory-contents');

            /**
             * Statically-cached template HTML used to render each file within
             * a directory. Once available, this will be used through
             * createFileElement() to generate the DOM elements which make up
             * a directory listing.
             *
             * @type String
             */
            var fileTemplate = null;

            /**
             * Returns whether the given file is a normal file.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a normal file, false otherwise.
             */
            $scope.isNormalFile = function isNormalFile(file) {
                return file.type === ManagedFilesystem.File.Type.NORMAL;
            };

            /**
             * Returns whether the given file is a directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a directory, false otherwise.
             */
            $scope.isDirectory = function isDirectory(file) {
                return file.type === ManagedFilesystem.File.Type.DIRECTORY;
            };

            /**
             * Changes the currently-displayed directory to the given
             * directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The directory to change to.
             */
            $scope.changeDirectory = function changeDirectory(file) {
                ManagedFilesystem.changeDirectory($scope.filesystem, file);
            };

            /**
             * Initiates a download of the given file. The progress of the
             * download can be observed through guacFileTransferManager.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to download.
             */
            $scope.downloadFile = function downloadFile(file) {
                ManagedFilesystem.downloadFile($scope.client, $scope.filesystem, file.streamName);
            };

            /**
             * Creates a new element representing the given file and properly
             * handling user events, bypassing the overhead incurred through
             * use of ngRepeat and related techniques.
             *
             * Note that this function depends on the availability of the
             * statically-cached fileTemplate.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to generate an element for.
             *
             * @returns {Element[]}
             *     A jQuery-wrapped array containing a single DOM element
             *     representing the given file.
             */
            var createFileElement = function createFileElement(file) {

                // Create from internal template
                var element = angular.element($interpolate(fileTemplate)(file));

                // Double-clicking on unknown file types will do nothing
                var fileAction = function doNothing() {};

                // Change current directory when directories are clicked
                if ($scope.isDirectory(file)) {
                    element.addClass('directory');
                    fileAction = function changeDirectory() {
                        $scope.changeDirectory(file);
                    };
                }

                // Initiate downloads when normal files are clicked
                else if ($scope.isNormalFile(file)) {
                    element.addClass('normal-file');
                    fileAction = function downloadFile() {
                        $scope.downloadFile(file);
                    };
                }

                // Mark file as focused upon click
                element.on('click', function focusFile(e) {

                    // Fire file-specific action if already focused
                    if (element.hasClass('focused'))
                        fileAction();

                    // Otherwise mark as focused
                    else {
                        element.parent().children().removeClass('focused');
                        element.addClass('focused');
                    }

                    // Do not allow default action
                    e.preventDefault();
                    e.stopPropagation();

                });

                // Prevent text selection during navigation
                element.on('selectstart', function avoidSelect(e) {
                    e.preventDefault();
                    e.stopPropagation();
                });

                return element;

            };

            /**
             * Sorts the given map of files, returning an array of those files
             * grouped by file type (directories first, followed by non-
             * directories) and sorted lexicographically.
             *
             * @param {Object.<String, ManagedFilesystem.File>} files
             *     The map of files to sort.
             *
             * @returns {ManagedFilesystem.File[]}
             *     An array of all files in the given map, sorted
             *     lexicographically with directories first, followed by non-
             *     directories.
             */
            var sortFiles = function sortFiles(files) {

                // Get all given files as an array
                var unsortedFiles = [];
                for (var name in files)
                    unsortedFiles.push(files[name]);

                // Sort files - directories first, followed by all other files
                // sorted by name
                return unsortedFiles.sort(function fileComparator(a, b) {

                    // Directories come before non-directories
                    if ($scope.isDirectory(a) && !$scope.isDirectory(b))
                        return -1;

                    // Non-directories come after directories
                    if (!$scope.isDirectory(a) && $scope.isDirectory(b))
                        return 1;

                    // All other combinations are sorted by name
                    return a.name.localeCompare(b.name);

                });

            };

            // Watch directory contents once file template is available
            $templateRequest('app/client/templates/file.html').then(function fileTemplateRetrieved(html) {

                // Store file template statically
                fileTemplate = html;

                // Update the contents of the file browser whenever the current directory (or its contents) changes
                $scope.$watch('filesystem.currentDirectory.files', function currentDirectoryChanged(files) {

                    // Clear current content
                    currentDirectoryContents.html('');

                    // Display all files within current directory, sorted
                    angular.forEach(sortFiles(files), function displayFile(file) {
                        currentDirectoryContents.append(createFileElement(file));
                    });

                });

            }); // end retrieve file template

        }]

    };
}]);
<commit_msg>GUAC-1293: Remove "focused" class after action is fired.<commit_after>/*
 * Copyright (C) 2015 Glyptodon LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * A directive which displays the contents of a filesystem received through the
 * Guacamole client.
 */
angular.module('client').directive('guacFileBrowser', [function guacFileBrowser() {

    return {
        restrict: 'E',
        replace: true,
        scope: {

            /**
             * The client whose file transfers should be managed by this
             * directive.
             *
             * @type ManagedClient
             */
            client : '=',

            /**
             * @type ManagedFilesystem
             */
            filesystem : '='

        },

        templateUrl: 'app/client/templates/guacFileBrowser.html',
        controller: ['$scope', '$element', '$injector', function guacFileBrowserController($scope, $element, $injector) {

            // Required types
            var ManagedFilesystem = $injector.get('ManagedFilesystem');

            // Required services
            var $interpolate     = $injector.get('$interpolate');
            var $templateRequest = $injector.get('$templateRequest');

            /**
             * The jQuery-wrapped element representing the contents of the
             * current directory within the file browser.
             *
             * @type Element[]
             */
            var currentDirectoryContents = $element.find('.current-directory-contents');

            /**
             * Statically-cached template HTML used to render each file within
             * a directory. Once available, this will be used through
             * createFileElement() to generate the DOM elements which make up
             * a directory listing.
             *
             * @type String
             */
            var fileTemplate = null;

            /**
             * Returns whether the given file is a normal file.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a normal file, false otherwise.
             */
            $scope.isNormalFile = function isNormalFile(file) {
                return file.type === ManagedFilesystem.File.Type.NORMAL;
            };

            /**
             * Returns whether the given file is a directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a directory, false otherwise.
             */
            $scope.isDirectory = function isDirectory(file) {
                return file.type === ManagedFilesystem.File.Type.DIRECTORY;
            };

            /**
             * Changes the currently-displayed directory to the given
             * directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The directory to change to.
             */
            $scope.changeDirectory = function changeDirectory(file) {
                ManagedFilesystem.changeDirectory($scope.filesystem, file);
            };

            /**
             * Initiates a download of the given file. The progress of the
             * download can be observed through guacFileTransferManager.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to download.
             */
            $scope.downloadFile = function downloadFile(file) {
                ManagedFilesystem.downloadFile($scope.client, $scope.filesystem, file.streamName);
            };

            /**
             * Creates a new element representing the given file and properly
             * handling user events, bypassing the overhead incurred through
             * use of ngRepeat and related techniques.
             *
             * Note that this function depends on the availability of the
             * statically-cached fileTemplate.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to generate an element for.
             *
             * @returns {Element[]}
             *     A jQuery-wrapped array containing a single DOM element
             *     representing the given file.
             */
            var createFileElement = function createFileElement(file) {

                // Create from internal template
                var element = angular.element($interpolate(fileTemplate)(file));

                // Double-clicking on unknown file types will do nothing
                var fileAction = function doNothing() {};

                // Change current directory when directories are clicked
                if ($scope.isDirectory(file)) {
                    element.addClass('directory');
                    fileAction = function changeDirectory() {
                        $scope.changeDirectory(file);
                    };
                }

                // Initiate downloads when normal files are clicked
                else if ($scope.isNormalFile(file)) {
                    element.addClass('normal-file');
                    fileAction = function downloadFile() {
                        $scope.downloadFile(file);
                    };
                }

                // Mark file as focused upon click
                element.on('click', function focusFile(e) {

                    // Fire file-specific action if already focused
                    if (element.hasClass('focused')) {
                        fileAction();
                        element.removeClass('focused');
                    }

                    // Otherwise mark as focused
                    else {
                        element.parent().children().removeClass('focused');
                        element.addClass('focused');
                    }

                    // Do not allow default action
                    e.preventDefault();
                    e.stopPropagation();

                });

                // Prevent text selection during navigation
                element.on('selectstart', function avoidSelect(e) {
                    e.preventDefault();
                    e.stopPropagation();
                });

                return element;

            };

            /**
             * Sorts the given map of files, returning an array of those files
             * grouped by file type (directories first, followed by non-
             * directories) and sorted lexicographically.
             *
             * @param {Object.<String, ManagedFilesystem.File>} files
             *     The map of files to sort.
             *
             * @returns {ManagedFilesystem.File[]}
             *     An array of all files in the given map, sorted
             *     lexicographically with directories first, followed by non-
             *     directories.
             */
            var sortFiles = function sortFiles(files) {

                // Get all given files as an array
                var unsortedFiles = [];
                for (var name in files)
                    unsortedFiles.push(files[name]);

                // Sort files - directories first, followed by all other files
                // sorted by name
                return unsortedFiles.sort(function fileComparator(a, b) {

                    // Directories come before non-directories
                    if ($scope.isDirectory(a) && !$scope.isDirectory(b))
                        return -1;

                    // Non-directories come after directories
                    if (!$scope.isDirectory(a) && $scope.isDirectory(b))
                        return 1;

                    // All other combinations are sorted by name
                    return a.name.localeCompare(b.name);

                });

            };

            // Watch directory contents once file template is available
            $templateRequest('app/client/templates/file.html').then(function fileTemplateRetrieved(html) {

                // Store file template statically
                fileTemplate = html;

                // Update the contents of the file browser whenever the current directory (or its contents) changes
                $scope.$watch('filesystem.currentDirectory.files', function currentDirectoryChanged(files) {

                    // Clear current content
                    currentDirectoryContents.html('');

                    // Display all files within current directory, sorted
                    angular.forEach(sortFiles(files), function displayFile(file) {
                        currentDirectoryContents.append(createFileElement(file));
                    });

                });

            }); // end retrieve file template

        }]

    };
}]);
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.9.3
// (function(){var e;e=function(){function e(e,t){var n,r;this.options={target:"instafeed",get:"popular",resolution:"thumbnail",sortBy:"none",links:!0,mock:!1,useHttp:!1};if(typeof e=="object")for(n in e)r=e[n],this.options[n]=r;this.context=t!=null?t:this,this.unique=this._genKey()}return e.prototype.hasNext=function(){return typeof this.context.nextUrl=="string"&&this.context.nextUrl.length>0},e.prototype.next=function(){return
// this.hasNext()?this.run(this.context.nextUrl):!1},e.prototype.run=function(t){var n,r,i;if(typeof this.options.clientId!="string"&&typeof this.options.accessToken!="string")throw new Error("Missing clientId or accessToken.");if(typeof this.options.accessToken!="string"&&typeof this.options.clientId!="string")throw new Error("Missing clientId or accessToken.");return this.options.before!=null&&typeof
// this.options.before=="function"&&this.options.before.call(this),typeof document!="undefined"&&document!==null&&(i=document.createElement("script"),i.id="instafeed-fetcher",i.src=t||this._buildUrl(),n=document.getElementsByTagName("head"),n[0].appendChild(i),r="instafeedCache"+this.unique,window[r]=new e(this.options,this),window[r].unique=this.unique),!0},e.prototype.parse=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D;if(typeof
// e!="object"){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,"Invalid JSON data"),!1;throw new Error("Invalid JSON response")}if(e.meta.code!==200){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,e.meta.error_message),!1;throw new Error("Error from Instagram: "+e.meta.error_message)}if(e.data.length===0){if(this.options.error!=null&&typeof
// this.options.error=="function")return this.options.error.call(this,"No images were returned from Instagram"),!1;throw new Error("No images were returned from Instagram")}this.options.success!=null&&typeof
// this.options.success=="function"&&this.options.success.call(this,e),this.context.nextUrl="",e.pagination!=null&&(this.context.nextUrl=e.pagination.next_url);if(this.options.sortBy!=="none"){this.options.sortBy==="random"?M=["","random"]:M=this.options.sortBy.split("-"),O=M[0]==="least"?!0:!1;switch(M[1]){case"random":e.data.sort(function(){return.5-Math.random()});break;case"recent":e.data=this._sortBy(e.data,"created_time",O);break;case"liked":e.data=this._sortBy(e.data,"likes.count",O);break;case"commented":e.data=this._sortBy(e.data,"comments.count",O);break;default:throw
// new Error("Invalid option for sortBy: '"+this.options.sortBy+"'.")}}if(typeof document!="undefined"&&document!==null&&this.options.mock===!1){m=e.data,A=parseInt(this.options.limit,10),this.options.limit!=null&&m.length>A&&(m=m.slice(0,A)),u=document.createDocumentFragment(),this.options.filter!=null&&typeof this.options.filter=="function"&&(m=this._filter(m,this.options.filter));if(this.options.template!=null&&typeof
// this.options.template=="string"){f="",d="",w="",D=document.createElement("div");for(c=0,N=m.length;c<N;c++){h=m[c],p=h.images[this.options.resolution];if(typeof p!="object")throw o="No image found for resolution: "+this.options.resolution+".",new
// Error(o);E=p.width,y=p.height,b="square",E>y&&(b="landscape"),E<y&&(b="portrait"),v=p.url,l=window.location.protocol.indexOf("http")>=0,l&&!this.options.useHttp&&(v=v.replace(/https?:\/\//,"//")),d=this._makeTemplate(this.options.template,{model:h,id:h.id,link:h.link,type:h.type,image:v,width:E,height:y,orientation:b,caption:this._getObjectProperty(h,"caption.text"),likes:h.likes.count,comments:h.comments.count,location:this._getObjectProperty(h,"location.name")}),f+=d}D.innerHTML=f,i=[],r=0,n=D.childNodes.length;while(r<n)i.push(D.childNodes[r]),r+=1;for(x=0,C=i.length;x<C;x++)L=i[x],u.appendChild(L)}else
// for(T=0,k=m.length;T<k;T++){h=m[T],g=document.createElement("img"),p=h.images[this.options.resolution];if(typeof p!="object")throw o="No image found for resolution: "+this.options.resolution+".",new Error(o);v=p.url,l=window.location.protocol.indexOf("http")>=0,l&&!this.options.useHttp&&(v=v.replace(/https?:\/\//,"//")),g.src=v,this.options.links===!0?(t=document.createElement("a"),t.href=h.link,t.appendChild(g),u.appendChild(t)):u.appendChild(g)}_=this.options.target,typeof
// _=="string"&&(_=document.getElementById(_));if(_==null)throw o='No element with id="'+this.options.target+'" on page.',new Error(o);_.appendChild(u),a=document.getElementsByTagName("head")[0],a.removeChild(document.getElementById("instafeed-fetcher")),S="instafeedCache"+this.unique,window[S]=void 0;try{delete window[S]}catch(P){s=P}}return this.options.after!=null&&typeof
// this.options.after=="function"&&this.options.after.call(this),!0},e.prototype._buildUrl=function(){var e,t,n;e="https://api.instagram.com/v1";switch(this.options.get){case"popular":t="media/popular";break;case"tagged":if(!this.options.tagName)throw new Error("No tag name specified. Use the 'tagName' option.");t="tags/"+this.options.tagName+"/media/recent";break;case"location":if(!this.options.locationId)throw new Error("No location specified. Use the 'locationId'
// option.");t="locations/"+this.options.locationId+"/media/recent";break;case"user":if(!this.options.userId)throw new Error("No user specified. Use the 'userId' option.");t="users/"+this.options.userId+"/media/recent";break;default:throw new Error("Invalid option for get: '"+this.options.get+"'.")}return
// n=e+"/"+t,this.options.accessToken!=null?n+="?access_token="+this.options.accessToken:n+="?client_id="+this.options.clientId,this.options.limit!=null&&(n+="&count="+this.options.limit),n+="&callback=instafeedCache"+this.unique+".parse",n},e.prototype._genKey=function(){var e;return e=function(){return((1+Math.random())*65536|0).toString(16).substring(1)},""+e()+e()+e()+e()},e.prototype._makeTemplate=function(e,t){var
// n,r,i,s,o;r=/(?:\{{2})([\w\[\]\.]+)(?:\}{2})/,n=e;while(r.test(n))s=n.match(r)[1],o=(i=this._getObjectProperty(t,s))!=null?i:"",n=n.replace(r,function(){return""+o});return n},e.prototype._getObjectProperty=function(e,t){var n,r;t=t.replace(/\[(\w+)\]/g,".$1"),r=t.split(".");while(r.length){n=r.shift();if(!(e!=null&&n in e))return null;e=e[n]}return e},e.prototype._sortBy=function(e,t,n){var r;return r=function(e,r){var i,s;return
// i=this._getObjectProperty(e,t),s=this._getObjectProperty(r,t),n?i>s?1:-1:i<s?1:-1},e.sort(r.bind(this)),e},e.prototype._filter=function(e,t){var n,r,i,s,o;n=[],r=function(e){if(t(e))return n.push(e)};for(i=0,o=e.length;i<o;i++)s=e[i],r(s);return n},e}(),function(e,t){return typeof define=="function"&&define.amd?define([],t):typeof module=="object"&&module.exports?module.exports=t():e.Instafeed=t()}(this,function(){return e})}).call(this);
<commit_msg>remove comments<commit_after>// Generated by CoffeeScript 1.9.3
(function(){var e;e=function(){function e(e,t){var n,r;this.options={target:"instafeed",get:"popular",resolution:"thumbnail",sortBy:"none",links:!0,mock:!1,useHttp:!1};if(typeof e=="object")for(n in e)r=e[n],this.options[n]=r;this.context=t!=null?t:this,this.unique=this._genKey()}return e.prototype.hasNext=function(){return typeof this.context.nextUrl=="string"&&this.context.nextUrl.length>0},e.prototype.next=function(){return
this.hasNext()?this.run(this.context.nextUrl):!1},e.prototype.run=function(t){var n,r,i;if(typeof this.options.clientId!="string"&&typeof this.options.accessToken!="string")throw new Error("Missing clientId or accessToken.");if(typeof this.options.accessToken!="string"&&typeof this.options.clientId!="string")throw new Error("Missing clientId or accessToken.");return this.options.before!=null&&typeof
this.options.before=="function"&&this.options.before.call(this),typeof document!="undefined"&&document!==null&&(i=document.createElement("script"),i.id="instafeed-fetcher",i.src=t||this._buildUrl(),n=document.getElementsByTagName("head"),n[0].appendChild(i),r="instafeedCache"+this.unique,window[r]=new e(this.options,this),window[r].unique=this.unique),!0},e.prototype.parse=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D;if(typeof
e!="object"){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,"Invalid JSON data"),!1;throw new Error("Invalid JSON response")}if(e.meta.code!==200){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,e.meta.error_message),!1;throw new Error("Error from Instagram: "+e.meta.error_message)}if(e.data.length===0){if(this.options.error!=null&&typeof
this.options.error=="function")return this.options.error.call(this,"No images were returned from Instagram"),!1;throw new Error("No images were returned from Instagram")}this.options.success!=null&&typeof
this.options.success=="function"&&this.options.success.call(this,e),this.context.nextUrl="",e.pagination!=null&&(this.context.nextUrl=e.pagination.next_url);if(this.options.sortBy!=="none"){this.options.sortBy==="random"?M=["","random"]:M=this.options.sortBy.split("-"),O=M[0]==="least"?!0:!1;switch(M[1]){case"random":e.data.sort(function(){return.5-Math.random()});break;case"recent":e.data=this._sortBy(e.data,"created_time",O);break;case"liked":e.data=this._sortBy(e.data,"likes.count",O);break;case"commented":e.data=this._sortBy(e.data,"comments.count",O);break;default:throw
new Error("Invalid option for sortBy: '"+this.options.sortBy+"'.")}}if(typeof document!="undefined"&&document!==null&&this.options.mock===!1){m=e.data,A=parseInt(this.options.limit,10),this.options.limit!=null&&m.length>A&&(m=m.slice(0,A)),u=document.createDocumentFragment(),this.options.filter!=null&&typeof this.options.filter=="function"&&(m=this._filter(m,this.options.filter));if(this.options.template!=null&&typeof
this.options.template=="string"){f="",d="",w="",D=document.createElement("div");for(c=0,N=m.length;c<N;c++){h=m[c],p=h.images[this.options.resolution];if(typeof p!="object")throw o="No image found for resolution: "+this.options.resolution+".",new
Error(o);E=p.width,y=p.height,b="square",E>y&&(b="landscape"),E<y&&(b="portrait"),v=p.url,l=window.location.protocol.indexOf("http")>=0,l&&!this.options.useHttp&&(v=v.replace(/https?:\/\//,"//")),d=this._makeTemplate(this.options.template,{model:h,id:h.id,link:h.link,type:h.type,image:v,width:E,height:y,orientation:b,caption:this._getObjectProperty(h,"caption.text"),likes:h.likes.count,comments:h.comments.count,location:this._getObjectProperty(h,"location.name")}),f+=d}D.innerHTML=f,i=[],r=0,n=D.childNodes.length;while(r<n)i.push(D.childNodes[r]),r+=1;for(x=0,C=i.length;x<C;x++)L=i[x],u.appendChild(L)}else
for(T=0,k=m.length;T<k;T++){h=m[T],g=document.createElement("img"),p=h.images[this.options.resolution];if(typeof p!="object")throw o="No image found for resolution: "+this.options.resolution+".",new Error(o);v=p.url,l=window.location.protocol.indexOf("http")>=0,l&&!this.options.useHttp&&(v=v.replace(/https?:\/\//,"//")),g.src=v,this.options.links===!0?(t=document.createElement("a"),t.href=h.link,t.appendChild(g),u.appendChild(t)):u.appendChild(g)}_=this.options.target,typeof
_=="string"&&(_=document.getElementById(_));if(_==null)throw o='No element with id="'+this.options.target+'" on page.',new Error(o);_.appendChild(u),a=document.getElementsByTagName("head")[0],a.removeChild(document.getElementById("instafeed-fetcher")),S="instafeedCache"+this.unique,window[S]=void 0;try{delete window[S]}catch(P){s=P}}return this.options.after!=null&&typeof
this.options.after=="function"&&this.options.after.call(this),!0},e.prototype._buildUrl=function(){var e,t,n;e="https://api.instagram.com/v1";switch(this.options.get){case"popular":t="media/popular";break;case"tagged":if(!this.options.tagName)throw new Error("No tag name specified. Use the 'tagName' option.");t="tags/"+this.options.tagName+"/media/recent";break;case"location":if(!this.options.locationId)throw new Error("No location specified. Use the 'locationId'
option.");t="locations/"+this.options.locationId+"/media/recent";break;case"user":if(!this.options.userId)throw new Error("No user specified. Use the 'userId' option.");t="users/"+this.options.userId+"/media/recent";break;default:throw new Error("Invalid option for get: '"+this.options.get+"'.")}return
n=e+"/"+t,this.options.accessToken!=null?n+="?access_token="+this.options.accessToken:n+="?client_id="+this.options.clientId,this.options.limit!=null&&(n+="&count="+this.options.limit),n+="&callback=instafeedCache"+this.unique+".parse",n},e.prototype._genKey=function(){var e;return e=function(){return((1+Math.random())*65536|0).toString(16).substring(1)},""+e()+e()+e()+e()},e.prototype._makeTemplate=function(e,t){var
n,r,i,s,o;r=/(?:\{{2})([\w\[\]\.]+)(?:\}{2})/,n=e;while(r.test(n))s=n.match(r)[1],o=(i=this._getObjectProperty(t,s))!=null?i:"",n=n.replace(r,function(){return""+o});return n},e.prototype._getObjectProperty=function(e,t){var n,r;t=t.replace(/\[(\w+)\]/g,".$1"),r=t.split(".");while(r.length){n=r.shift();if(!(e!=null&&n in e))return null;e=e[n]}return e},e.prototype._sortBy=function(e,t,n){var r;return r=function(e,r){var i,s;return
i=this._getObjectProperty(e,t),s=this._getObjectProperty(r,t),n?i>s?1:-1:i<s?1:-1},e.sort(r.bind(this)),e},e.prototype._filter=function(e,t){var n,r,i,s,o;n=[],r=function(e){if(t(e))return n.push(e)};for(i=0,o=e.length;i<o;i++)s=e[i],r(s);return n},e}(),function(e,t){return typeof define=="function"&&define.amd?define([],t):typeof module=="object"&&module.exports?module.exports=t():e.Instafeed=t()}(this,function(){return e})}).call(this);
<|endoftext|>


<commit_before>!function(n,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("instantly",[],t):"object"==typeof exports?exports.instantly=t():n.instantly=t()}(this,function(){return function(n){function t(o){if(e[o])return e[o].exports;var r=e[o]={exports:{},id:o,loaded:!1};return n[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var e={};return t.m=n,t.c=e,t.p="",t(0)}([function(n,t,e){n.exports=e(3)},function(n,t){function e(n){return o(n)&&c.call(n)==r}function o(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}var r="[object Function]",i=Object.prototype,c=i.toString;n.exports=e},function(n,t){function e(n){return!!n&&"object"==typeof n}function o(n){return"string"==typeof n||e(n)&&c.call(n)==r}var r="[object String]",i=Object.prototype,c=i.toString;n.exports=o},function(n,t,e){"use strict";function o(n,t){function e(n,t){if(!i(t))throw new TypeError("Callback is not a function");if(!r(n))throw new TypeError("Event is not a string");g[n]=t}function o(){if(d){b=new d(n),b.addEventListener("open",l),b.addEventListener("error",a);for(var t in g){if(!g.hasOwnProperty(t))return;c(t)}}}function c(n){b.addEventListener(n,function(t){p&&t.origin!==p||(("CLOSE"===t.id||"CLOSE"===t.lastEventId)&&f(),g[n].call(null,t))})}function u(){j||m===v||setTimeout(function(){o(),m++},y)}function l(n){j=!0,m=0,E&&E.call(null,n)}function f(){b.close(),j=!1,x&&x.call(null)}function a(n){f(),u(),w&&w.call(null,n)}function s(){document.hidden?f():o()}if(!n)throw new TypeError("You need to provide a channel we can listen to!");t||(t={});var d;t.injectEventSourceNode?d=t.injectEventSourceNode:"undefined"!=typeof window&&window.EventSource&&(d=window.EventSource);var p=t.origin||null,v=t.retries||5,y=t.timeout||15e3,w=i(t.error)?t.error:null,E=i(t.open)?t.open:null,x=i(t.close)?t.close:null;t.closeConnNotFocus&&"undefined"!=typeof document&&document.addEventListener("visibilitychange",s);var b,j=!1,g={},m=0;return{on:e,listen:o,generateCallback:c,retry:u,close:f,error:a}}var r=e(2),i=e(1);n.exports=o}])});<commit_msg>update dist<commit_after>!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Instantly",[],e):"object"==typeof exports?exports.Instantly=e():t.Instantly=e()}(this,function(){return function(t){function e(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return t[i].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){t.exports=n(3)},function(t,e){function n(t){return i(t)&&s.call(t)==o}function i(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}var o="[object Function]",r=Object.prototype,s=r.toString;t.exports=n},function(t,e){function n(t){return!!t&&"object"==typeof t}function i(t){return"string"==typeof t||n(t)&&s.call(t)==o}var o="[object String]",r=Object.prototype,s=r.toString;t.exports=i},function(t,e,n){"use strict";function i(t,e){if(!t)throw new TypeError("You need to provide a channel we can listen to!");this.channel=t,e||(e={}),e.injectEventSourceNode?this.EventSource=e.injectEventSourceNode:"undefined"!=typeof window&&window.EventSource&&(this.EventSource=window.EventSource),this.origin=e.origin||null,this.retries=e.retries||5,this.timeout=e.timeout||15e3,this.errorHandler=r(e.error)?e.error:null,this.onOpen=r(e.open)?e.open:null,this.onClose=r(e.close)?e.close:null,e.closeConnNotFocus&&"undefined"!=typeof document&&document.addEventListener("visibilitychange",this.onVisibilityChange.bind(this))}var o=n(2),r=n(1);i.prototype={initialized:!1,callbacks:{},internalRetry:0,on:function(t,e){if(!r(e))throw new TypeError("Callback is not a function");if(!o(t))throw new TypeError("Event is not a string");this.callbacks[t]=e},listen:function(){if(this.EventSource){this.es=new this.EventSource(this.channel),this.es.addEventListener("open",this.open.bind(this)),this.es.addEventListener("error",this.error.bind(this));for(var t in this.callbacks){if(!this.callbacks.hasOwnProperty(t))return;this.generateCallback(t)}}},generateCallback:function(t){this.es.addEventListener(t,function(e){this.origin&&e.origin!==this.origin||(("CLOSE"===e.id||"CLOSE"===e.lastEventId)&&this.close(),this.callbacks[t].call(null,e))}.bind(this))},retry:function(){this.initialized||this.internalRetry===this.retries||setTimeout(function(){this.listen(),this.internalRetry++}.bind(this),this.timeout)},open:function(t){this.initialized=!0,this.internalRetry=0,this.onOpen&&this.onOpen.call(null,t)},close:function(){this.es.close(),this.initialized=!1,this.onClose&&this.onClose.call(null)},error:function(t){this.close(),this.retry(),this.errorHandler&&this.errorHandler.call(null,t)},onVisibilityChange:function(){document.hidden?this.close():this.listen()}},t.exports=i}])});<|endoftext|>


<commit_before>/*
Copyright 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import React from 'react';
import GeminiScrollbar from 'react-gemini-scrollbar';
import request from 'browser-request';
import { _t } from 'matrix-react-sdk/lib/languageHandler';
import sanitizeHtml from 'sanitize-html';

module.exports = React.createClass({
    displayName: 'HomePage',

    propTypes: {
        // URL base of the team server. Optional.
        teamServerUrl: React.PropTypes.string,
        // Team token. Optional. If set, used to get the static homepage of the team
        //      associated. If unset, homePageUrl will be used.
        teamToken: React.PropTypes.string,
        // URL to use as the iFrame src. Defaults to /home.html.
        homePageUrl: React.PropTypes.string,
    },

    getInitialState: function() {
        return {
            iframeSrc: '',
            page: '',
        };
    },

    translate: function(s) {
        s = sanitizeHtml(_t(s));
        // ugly fix for https://github.com/vector-im/riot-web/issues/4243
        s = s.replace(/Riot\.im/, 'Riot.im');
        s = s.replace(/\[matrix\]/, '');
        return s;
    },

    componentWillMount: function() {
        this._unmounted = false;

        if (this.props.teamToken && this.props.teamServerUrl) {
            this.setState({
                iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
            });
        }
        else {
            // we use request() to inline the homepage into the react component
            // so that it can inherit CSS and theming easily rather than mess around
            // with iframes and trying to synchronise document.stylesheets.

            let src = this.props.homePageUrl || 'home.html';

            request(
                { method: "GET", url: src },
                (err, response, body) => {
                    if (this._unmounted) {
                        return;
                    }

                    if (err || response.status < 200 || response.status >= 300) {
                        console.log(err);
                        this.setState({ page: "Couldn't load home page" });
                        return;
                    }

                    body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
                    this.setState({ page: body });
                }
            );
        }
    },

    componentWillUnmount: function() {
        this._unmounted = true;
    },

    render: function() {
        if (this.state.iframeSrc) {
            return (

            );
        }
        else {
            return (
                <GeminiScrollbar autoshow={true} className="mx_HomePage">

                </GeminiScrollbar>
            );
        }
    }
});
<commit_msg>more HomePage tweaks<commit_after>/*
Copyright 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

import React from 'react';
import GeminiScrollbar from 'react-gemini-scrollbar';
import request from 'browser-request';
import { _t } from 'matrix-react-sdk/lib/languageHandler';
import sanitizeHtml from 'sanitize-html';

module.exports = React.createClass({
    displayName: 'HomePage',

    propTypes: {
        // URL base of the team server. Optional.
        teamServerUrl: React.PropTypes.string,
        // Team token. Optional. If set, used to get the static homepage of the team
        //      associated. If unset, homePageUrl will be used.
        teamToken: React.PropTypes.string,
        // URL to use as the iFrame src. Defaults to /home.html.
        homePageUrl: React.PropTypes.string,
    },

    getInitialState: function() {
        return {
            iframeSrc: '',
            page: '',
        };
    },

    translate: function(s) {
        s = sanitizeHtml(_t(s));
        // ugly fix for https://github.com/vector-im/riot-web/issues/4243
        s = s.replace(/Riot\.im/, 'Riot.im');
        s = s.replace(/\[matrix\]/, '');
        return s;
    },

    componentWillMount: function() {
        this._unmounted = false;

        if (this.props.teamToken && this.props.teamServerUrl) {
            this.setState({
                iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
            });
        }
        else {
            // we use request() to inline the homepage into the react component
            // so that it can inherit CSS and theming easily rather than mess around
            // with iframes and trying to synchronise document.stylesheets.

            let src = this.props.homePageUrl || 'home.html';

            request(
                { method: "GET", url: src },
                (err, response, body) => {
                    if (this._unmounted) {
                        return;
                    }

                    if (err || response.status < 200 || response.status >= 300) {
                        console.warn(`Error loading home page: ${err}`);
                        this.setState({ page: _t("Couldn't load home page") });
                        return;
                    }

                    body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
                    this.setState({ page: body });
                }
            );
        }
    },

    componentWillUnmount: function() {
        this._unmounted = true;
    },

    render: function() {
        if (this.state.iframeSrc) {
            return (

            );
        }
        else {
            return (
                <GeminiScrollbar autoshow={true} className="mx_HomePage">

                </GeminiScrollbar>
            );
        }
    }
});
<|endoftext|>


<commit_before>import $ from 'jquery';
import MouseTrap from 'mousetrap';
import 'jquery-ui/widgets/slider';

import Signal from '../../utils/signal';
import { state } from '../../state';
import { song } from '../../utils/songmanager';
import { player } from '../../audio/player';

import transportTemplate from './templates/transport.marko';

import modfile from '../../../data/onward.xm';

import styles from './styles.css';

export default class Transport {
  constructor(target) {
    this.target = target;
    this.lastTransport = undefined;

    MouseTrap.bind(["{", "}"], (e) => {
      state.set({
        transport: {
          step: e.key == "{" ? Math.max(0, state.transport.get("step") - 1) :
                               state.transport.get("step") + 1,
        },
      });
      e.preventDefault();
    });

    MouseTrap.bind(["\"", "|"], (e) => {
      state.set({
        transport: {
          octave: e.key == "\"" ? Math.max(0, state.transport.get("octave") - 1) :
                                  state.transport.get("octave") + 1,
        },
      });
      e.preventDefault();
    });

    Signal.connect(state, "transportChanged", this, "onTransportChanged");
    Signal.connect(song, "songChanged", this, "onSongChanged");
  }

  render() {
    $(this.target).append(transportTemplate.renderToString({transport: state.transport.toJS(), song: song.song}));

    $(this.target).find("#master-volume").slider({
      max: 1.0,
      min: 0.0,
      range: "min",
      step: 0.01,
      value: player.gainNode.gain.value,
      slide: (e, ui) => {
        player.gainNode.gain.value = ui.value;
      },
    });

    $(this.target).find('input').bind("enterKey", (e) => {
      state.set({
        transport: {
          step: parseInt($(this.target).find("#step").val()),
          octave: parseInt($(this.target).find("#octave").val()),
        },
      });
      song.setBPM(parseInt($(this.target).find("#bpm").val()));
      song.setSpeed(parseInt($(this.target).find("#speed").val()));
      $(this).blur();
    });
    $(this.target).find('input').keyup(function(e){
      if(e.keyCode == 13)
      {
        $(this).trigger("enterKey");
      }
    });
    $(this.target).find('#play').click((e) => {
      player.play();
    });
    $(this.target).find('#play-pattern').click((e) => {
      player.playPattern(state.cursor.get("pattern"));
    });
    $(this.target).find('#pause').click((e) => {
      player.pause();
    });
    $(this.target).find('#stop').click((e) => {
      player.stop();
    });
    $(this.target).find('#reset').click((e) => {
      player.reset();
    });
    $(this.target).find('#new').click((e) => {
      song.newSong();
    });
    $(this.target).find('#load').click((e) => {
      $( "#dialog" ).empty();
      $( "#dialog" ).append($("<input type=\"file\" id=\"file-input\" />"));
      $( "#dialog" ).dialog({
        width: 500,
        modal: true,
        buttons: {
          Ok: function() {
            var files = $("#file-input")[0].files;
            if (files.length > 0) {
              song.loadSongFromFile(files[0], (result) => {
                song.setSong(result);
              });
            }
            $( this ).dialog( "close" );
          },
          Cancel: function() {
            $( this ).dialog( "close" );
          },
          Demo: function() {
            song.downloadSong(modfile);
            $( this ).dialog( "close" );
          }
        }
      });
    });
    $(this.target).find('#save').click((e) => {
      song.saveSongToLocal();
    });
  }

  onTransportChanged() {
    if (this.lastTransport !== state.transport) {
      $(this.target).find("#step").val(state.transport.get("step"));
      $(this.target).find("#octave").val(state.transport.get("octave"));
      $(this.target).find("#bpm").val(state.transport.get("bpm"));
      $(this.target).find("#speed").val(state.transport.get("speed"));

      this.lastTransport = state.transport;
    }
  }

  refresh() {
    $(this.target).empty();
    this.render();
  }

  onSongChanged() {
    this.refresh();
  }
}
<commit_msg>Fix blurring input fields on enter.<commit_after>import $ from 'jquery';
import MouseTrap from 'mousetrap';
import 'jquery-ui/widgets/slider';

import Signal from '../../utils/signal';
import { state } from '../../state';
import { song } from '../../utils/songmanager';
import { player } from '../../audio/player';

import transportTemplate from './templates/transport.marko';

import modfile from '../../../data/onward.xm';

import styles from './styles.css';

export default class Transport {
  constructor(target) {
    this.target = target;
    this.lastTransport = undefined;

    MouseTrap.bind(["{", "}"], (e) => {
      state.set({
        transport: {
          step: e.key == "{" ? Math.max(0, state.transport.get("step") - 1) :
                               state.transport.get("step") + 1,
        },
      });
      e.preventDefault();
    });

    MouseTrap.bind(["\"", "|"], (e) => {
      state.set({
        transport: {
          octave: e.key == "\"" ? Math.max(0, state.transport.get("octave") - 1) :
                                  state.transport.get("octave") + 1,
        },
      });
      e.preventDefault();
    });

    Signal.connect(state, "transportChanged", this, "onTransportChanged");
    Signal.connect(song, "songChanged", this, "onSongChanged");
  }

  render() {
    $(this.target).append(transportTemplate.renderToString({transport: state.transport.toJS(), song: song.song}));

    $(this.target).find("#master-volume").slider({
      max: 1.0,
      min: 0.0,
      range: "min",
      step: 0.01,
      value: player.gainNode.gain.value,
      slide: (e, ui) => {
        player.gainNode.gain.value = ui.value;
      },
    });

    $(this.target).find('input').bind("enterKey", (e) => {
      state.set({
        transport: {
          step: parseInt($(this.target).find("#step").val()),
          octave: parseInt($(this.target).find("#octave").val()),
        },
      });
      song.setBPM(parseInt($(this.target).find("#bpm").val()));
      song.setSpeed(parseInt($(this.target).find("#speed").val()));
      $(e.target).blur();
    });
    $(this.target).find('input').keyup(function(e){
      if(e.keyCode == 13)
      {
        $(this).trigger("enterKey");
      }
    });
    $(this.target).find('#play').click((e) => {
      player.play();
    });
    $(this.target).find('#play-pattern').click((e) => {
      player.playPattern(state.cursor.get("pattern"));
    });
    $(this.target).find('#pause').click((e) => {
      player.pause();
    });
    $(this.target).find('#stop').click((e) => {
      player.stop();
    });
    $(this.target).find('#reset').click((e) => {
      player.reset();
    });
    $(this.target).find('#new').click((e) => {
      song.newSong();
    });
    $(this.target).find('#load').click((e) => {
      $( "#dialog" ).empty();
      $( "#dialog" ).append($("<input type=\"file\" id=\"file-input\" />"));
      $( "#dialog" ).dialog({
        width: 500,
        modal: true,
        buttons: {
          Ok: function() {
            var files = $("#file-input")[0].files;
            if (files.length > 0) {
              song.loadSongFromFile(files[0], (result) => {
                song.setSong(result);
              });
            }
            $( this ).dialog( "close" );
          },
          Cancel: function() {
            $( this ).dialog( "close" );
          },
          Demo: function() {
            song.downloadSong(modfile);
            $( this ).dialog( "close" );
          }
        }
      });
    });
    $(this.target).find('#save').click((e) => {
      song.saveSongToLocal();
    });
  }

  onTransportChanged() {
    if (this.lastTransport !== state.transport) {
      $(this.target).find("#step").val(state.transport.get("step"));
      $(this.target).find("#octave").val(state.transport.get("octave"));
      $(this.target).find("#bpm").val(state.transport.get("bpm"));
      $(this.target).find("#speed").val(state.transport.get("speed"));

      this.lastTransport = state.transport;
    }
  }

  refresh() {
    $(this.target).empty();
    this.render();
  }

  onSongChanged() {
    this.refresh();
  }
}
<|endoftext|>


<commit_before>// jshint ignore: start
var gulp = require('gulp')
var standard = require('gulp-standard')
var uglify = require('gulp-uglify')
var concat = require('gulp-concat')
var sass = require('gulp-sass')
var sassLint = require('gulp-sass-lint')
var replace = require('gulp-replace')
var filesExist = require('files-exist')
var compass = require('compass-importer')

// Path variables
var nodeModulesPath = __dirname + '/../../../../../node_modules/'
var nodeModulesRelativePath = '../../../../../node_modules/'
var gdsFrontendToolkitPath = nodeModulesPath + 'govuk_frontend_toolkit/'
var gdsJinjaPath = nodeModulesPath + 'govuk_template_jinja/'
var gdsElementsPath = nodeModulesPath + 'govuk-elements-sass/'
var vendorImages = [
	gdsJinjaPath + 'assets/images/**/**',
  gdsJinjaPath + 'assets/stylesheets/images/**/**',
	gdsFrontendToolkitPath + 'images/**/**'
]
var sassFiles = [
	'./sass/**/*.scss',
	gdsFrontendToolkitPath + '**/*.scss',
	gdsElementsPath + '**/*.scss'
]
var vendorJsFiles = [
  nodeModulesPath + 'js-cookie/src/js.cookie.js',
  nodeModulesPath + 'jquery/dist/jquery.js',
  nodeModulesPath + 'simplestatemanager/src/ssm.js',
  'js/vendor/jquery-ui/jquery-ui.min.js',
  'js/vendor/govuk/*.js',
  '!js/vendor/govuk/ie.js',
  'js/vendor/wysiwyg-editor/*.js',
  '!js/vendor/wysiwyg-editor/hallo-src/*.js'
]

gulp.task('copy-govuk', ['copy-fonts-govuk', 'copy-images-govuk'])
// copy over the fonts from GDS node-modules to css/fonts folder
gulp.task('copy-fonts-govuk', function () {
  return gulp.src(filesExist(gdsJinjaPath + 'assets/stylesheets/fonts/*')).pipe(gulp.dest('css/fonts'))
})
//  copy over the images from GDS node-modules to images folder
gulp.task('copy-images-govuk', function () {
  return gulp.src(vendorImages).pipe(gulp.dest('images'))
})

gulp.task('default', ['js', 'css'])

// build all js
gulp.task('js', ['vendor', 'ifs-js'])

// concat and minify all the ifs files
gulp.task('ifs-js', function () {
  return gulp.src([
    'js/ifsCoreLoader.js',
    'js/ifs_modules/*.js',
    'js/ifs_pages/*.js',
    'js/fire.js'
  ])
  .pipe(standard())
  .pipe(concat('ifs.min.js'))
  .pipe(uglify())
  .pipe(gulp.dest('js/dest'))
  .pipe(standard.reporter('default', {
    breakOnError: true,
    breakOnWarning: false,
    quiet: false
  }))
})

// concat and minify all the vendor files
gulp.task('vendor', function () {
  return gulp.src(filesExist(vendorJsFiles))
  .pipe(concat('vendor.min.js'))
  .pipe(uglify())
  .pipe(gulp.dest('js/dest'))
})

gulp.task('css', ['copy-govuk'], function () {
	return gulp.src(filesExist(sassFiles))
    .pipe(sassLint({
      files: {
        ignore: [
          '**/prototype.scss',
          '**/prototype/**/*.scss',
	        nodeModulesRelativePath + '**/*.scss'
        ]
      },
      config: '.sass-lint.yml'
    }))
    .pipe(sassLint.format())
    .pipe(sass({includePaths: [
		    gdsFrontendToolkitPath + 'stylesheets',
        gdsElementsPath + 'public/sass',
		    gdsJinjaPath + 'assets/stylesheets'
    ],
      importer: compass,
      outputStyle: 'compressed'
    }).on('error', sass.logError))
    .pipe(replace('url(images/', 'url(/images/'))
    .pipe(gulp.dest('./css'))
})

gulp.task('css:watch', function () {
  gulp.watch('./sass/**/*.scss', ['css'])
})

gulp.task('js:watch', function () {
  gulp.watch(['js/**/*.js', '!js/dest/*.js'], ['js'])
})<commit_msg>IFS-3338 Fix indentation<commit_after>// jshint ignore: start
var gulp = require('gulp')
var standard = require('gulp-standard')
var uglify = require('gulp-uglify')
var concat = require('gulp-concat')
var sass = require('gulp-sass')
var sassLint = require('gulp-sass-lint')
var replace = require('gulp-replace')
var filesExist = require('files-exist')
var compass = require('compass-importer')

// Path variables
var nodeModulesPath = __dirname + '/../../../../../node_modules/'
var nodeModulesRelativePath = '../../../../../node_modules/'
var gdsFrontendToolkitPath = nodeModulesPath + 'govuk_frontend_toolkit/'
var gdsJinjaPath = nodeModulesPath + 'govuk_template_jinja/'
var gdsElementsPath = nodeModulesPath + 'govuk-elements-sass/'
var vendorImages = [
  gdsJinjaPath + 'assets/images/**/**',
  gdsJinjaPath + 'assets/stylesheets/images/**/**',
  gdsFrontendToolkitPath + 'images/**/**'
]
var sassFiles = [
  './sass/**/*.scss',
  gdsFrontendToolkitPath + '**/*.scss',
  gdsElementsPath + '**/*.scss'
]
var vendorJsFiles = [
  nodeModulesPath + 'js-cookie/src/js.cookie.js',
  nodeModulesPath + 'jquery/dist/jquery.js',
  nodeModulesPath + 'simplestatemanager/src/ssm.js',
  'js/vendor/jquery-ui/jquery-ui.min.js',
  'js/vendor/govuk/*.js',
  '!js/vendor/govuk/ie.js',
  'js/vendor/wysiwyg-editor/*.js',
  '!js/vendor/wysiwyg-editor/hallo-src/*.js'
]

gulp.task('copy-govuk', ['copy-fonts-govuk', 'copy-images-govuk'])
// copy over the fonts from GDS node-modules to css/fonts folder
gulp.task('copy-fonts-govuk', function () {
  return gulp.src(filesExist(gdsJinjaPath + 'assets/stylesheets/fonts/*')).pipe(gulp.dest('css/fonts'))
})
//  copy over the images from GDS node-modules to images folder
gulp.task('copy-images-govuk', function () {
  return gulp.src(vendorImages).pipe(gulp.dest('images'))
})

gulp.task('default', ['js', 'css'])

// build all js
gulp.task('js', ['vendor', 'ifs-js'])

// concat and minify all the ifs files
gulp.task('ifs-js', function () {
  return gulp.src([
    'js/ifsCoreLoader.js',
    'js/ifs_modules/*.js',
    'js/ifs_pages/*.js',
    'js/fire.js'
  ])
  .pipe(standard())
  .pipe(concat('ifs.min.js'))
  .pipe(uglify())
  .pipe(gulp.dest('js/dest'))
  .pipe(standard.reporter('default', {
    breakOnError: true,
    breakOnWarning: false,
    quiet: false
  }))
})

// concat and minify all the vendor files
gulp.task('vendor', function () {
  return gulp.src(filesExist(vendorJsFiles))
  .pipe(concat('vendor.min.js'))
  .pipe(uglify())
  .pipe(gulp.dest('js/dest'))
})

gulp.task('css', ['copy-govuk'], function () {
	return gulp.src(filesExist(sassFiles))
    .pipe(sassLint({
      files: {
        ignore: [
          '**/prototype.scss',
          '**/prototype/**/*.scss',
	        nodeModulesRelativePath + '**/*.scss'
        ]
      },
      config: '.sass-lint.yml'
    }))
    .pipe(sassLint.format())
    .pipe(sass({includePaths: [
		  gdsFrontendToolkitPath + 'stylesheets',
      gdsElementsPath + 'public/sass',
		  gdsJinjaPath + 'assets/stylesheets'
    ],
      importer: compass,
      outputStyle: 'compressed'
    }).on('error', sass.logError))
    .pipe(replace('url(images/', 'url(/images/'))
    .pipe(gulp.dest('./css'))
})

gulp.task('css:watch', function () {
  gulp.watch('./sass/**/*.scss', ['css'])
})

gulp.task('js:watch', function () {
  gulp.watch(['js/**/*.js', '!js/dest/*.js'], ['js'])
})<|endoftext|>


<commit_before>// @flow
import React from 'react';
import { IS_BROWSER, STATIC_EXECUTION_CONTEXT } from '../constants';
import GlobalStyle from '../models/GlobalStyle';
import StyleSheet from '../models/StyleSheet';
import { StyleSheetConsumer } from '../models/StyleSheetManager';
import determineTheme from '../utils/determineTheme';
import { ThemeConsumer, type Theme } from '../models/ThemeProvider';
// $FlowFixMe
import hashStr from '../vendor/glamor/hash';
import css from './css';

import type { Interpolation } from '../types';

// place our cache into shared context so it'll persist between HMRs
if (IS_BROWSER) {
  window.scCGSHMRCache = {};
}

export default function createGlobalStyle(
  strings: Array<string>,
  ...interpolations: Array<Interpolation>
) {
  const rules = css(strings, ...interpolations);
  const id = `sc-global-${hashStr(JSON.stringify(rules))}`;
  const style = new GlobalStyle(rules, id);

  class GlobalStyleComponent extends React.Component<*, *> {
    styleSheet: Object;

    static globalStyle = style;

    static styledComponentId = id;

    constructor() {
      super();

      const { globalStyle, styledComponentId } = this.constructor;

      if (IS_BROWSER) {
        window.scCGSHMRCache[styledComponentId] =
          (window.scCGSHMRCache[styledComponentId] || 0) + 1;
      }

      /**
       * This fixes HMR compatiblility. Don't ask me why, but this combination of
       * caching the closure variables via statics and then persisting the statics in
       * state works across HMR where no other combination did. ¯\_(ツ)_/¯
       */
      this.state = {
        globalStyle,
        styledComponentId,
      };
    }

    componentWillUnmount() {
      if (window.scCGSHMRCache[this.state.styledComponentId]) {
        window.scCGSHMRCache[this.state.styledComponentId] -= 1;
      }
      /**
       * Depending on the order "render" is called this can cause the styles to be lost
       * until the next render pass of the remaining instance, which may
       * not be immediate.
       */
      if (window.scCGSHMRCache[this.state.styledComponentId] === 0) {
        this.state.globalStyle.removeStyles(this.styleSheet);
      }
    }

    render() {
      if (process.env.NODE_ENV !== 'production' && React.Children.count(this.props.children)) {
        // eslint-disable-next-line no-console
        console.warn(
          `The global style component ${
            this.state.styledComponentId
          } was given child JSX. createGlobalStyle does not render children.`
        );
      }

      return (
        <StyleSheetConsumer>
          {(styleSheet?: StyleSheet) => {
            this.styleSheet = styleSheet || StyleSheet.master;

            const { globalStyle } = this.state;

            if (globalStyle.isStatic) {
              globalStyle.renderStyles(STATIC_EXECUTION_CONTEXT, this.styleSheet);

              return null;
            } else {
              return (
                <ThemeConsumer>
                  {(theme?: Theme) => {
                    // $FlowFixMe
                    const { defaultProps } = this.constructor;

                    const context = {
                      ...this.props,
                    };

                    if (typeof theme !== 'undefined') {
                      context.theme = determineTheme(this.props, theme, defaultProps);
                    }

                    globalStyle.renderStyles(context, this.styleSheet);

                    return null;
                  }}
                </ThemeConsumer>
              );
            }
          }}
        </StyleSheetConsumer>
      );
    }
  }

  return GlobalStyleComponent;
}
<commit_msg>fix(createGlobalStyle): typo in the comment<commit_after>// @flow
import React from 'react';
import { IS_BROWSER, STATIC_EXECUTION_CONTEXT } from '../constants';
import GlobalStyle from '../models/GlobalStyle';
import StyleSheet from '../models/StyleSheet';
import { StyleSheetConsumer } from '../models/StyleSheetManager';
import determineTheme from '../utils/determineTheme';
import { ThemeConsumer, type Theme } from '../models/ThemeProvider';
// $FlowFixMe
import hashStr from '../vendor/glamor/hash';
import css from './css';

import type { Interpolation } from '../types';

// place our cache into shared context so it'll persist between HMRs
if (IS_BROWSER) {
  window.scCGSHMRCache = {};
}

export default function createGlobalStyle(
  strings: Array<string>,
  ...interpolations: Array<Interpolation>
) {
  const rules = css(strings, ...interpolations);
  const id = `sc-global-${hashStr(JSON.stringify(rules))}`;
  const style = new GlobalStyle(rules, id);

  class GlobalStyleComponent extends React.Component<*, *> {
    styleSheet: Object;

    static globalStyle = style;

    static styledComponentId = id;

    constructor() {
      super();

      const { globalStyle, styledComponentId } = this.constructor;

      if (IS_BROWSER) {
        window.scCGSHMRCache[styledComponentId] =
          (window.scCGSHMRCache[styledComponentId] || 0) + 1;
      }

      /**
       * This fixes HMR compatibility. Don't ask me why, but this combination of
       * caching the closure variables via statics and then persisting the statics in
       * state works across HMR where no other combination did. ¯\_(ツ)_/¯
       */
      this.state = {
        globalStyle,
        styledComponentId,
      };
    }

    componentWillUnmount() {
      if (window.scCGSHMRCache[this.state.styledComponentId]) {
        window.scCGSHMRCache[this.state.styledComponentId] -= 1;
      }
      /**
       * Depending on the order "render" is called this can cause the styles to be lost
       * until the next render pass of the remaining instance, which may
       * not be immediate.
       */
      if (window.scCGSHMRCache[this.state.styledComponentId] === 0) {
        this.state.globalStyle.removeStyles(this.styleSheet);
      }
    }

    render() {
      if (process.env.NODE_ENV !== 'production' && React.Children.count(this.props.children)) {
        // eslint-disable-next-line no-console
        console.warn(
          `The global style component ${
            this.state.styledComponentId
          } was given child JSX. createGlobalStyle does not render children.`
        );
      }

      return (
        <StyleSheetConsumer>
          {(styleSheet?: StyleSheet) => {
            this.styleSheet = styleSheet || StyleSheet.master;

            const { globalStyle } = this.state;

            if (globalStyle.isStatic) {
              globalStyle.renderStyles(STATIC_EXECUTION_CONTEXT, this.styleSheet);

              return null;
            } else {
              return (
                <ThemeConsumer>
                  {(theme?: Theme) => {
                    // $FlowFixMe
                    const { defaultProps } = this.constructor;

                    const context = {
                      ...this.props,
                    };

                    if (typeof theme !== 'undefined') {
                      context.theme = determineTheme(this.props, theme, defaultProps);
                    }

                    globalStyle.renderStyles(context, this.styleSheet);

                    return null;
                  }}
                </ThemeConsumer>
              );
            }
          }}
        </StyleSheetConsumer>
      );
    }
  }

  return GlobalStyleComponent;
}
<|endoftext|>


<commit_before>(function(doc) {

  log = noop; // noOp, remove this line to enable debugging

  var coordinateSystemForElementFromPoint;

  function main(config) {
    config = config || {};

    coordinateSystemForElementFromPoint = navigator.userAgent.match(/OS 5(?:_\d+)+ like Mac/) ? "client" : "page";

    var div = doc.createElement('div');
    var dragDiv = 'draggable' in div;
    var evts = 'ondragstart' in div && 'ondrop' in div;

    var needsPatch = !(dragDiv || evts) || /iPad|iPhone|iPod/.test(navigator.userAgent);
    log((needsPatch ? "" : "not ") + "patching html5 drag drop");

    if(!needsPatch) return;

    if(!config.enableEnterLeave) {
      DragDrop.prototype.synthesizeEnterLeave = noop;
    }

    doc.addEventListener("touchstart", touchstart);
  }

  function DragDrop(event, el) {

    this.touchPositions = {};
    this.dragData = {};
    this.el = el || event.target

    event.preventDefault();

    log("dragstart");

    this.dispatchDragStart()
    this.elTranslation = readTransform(this.el);

    this.listen()

  }

  DragDrop.prototype = {
    listen: function() {
      var move = onEvt(doc, "touchmove", this.move, this);
      var end = onEvt(doc, "touchend", ontouchend, this);
      var cancel = onEvt(doc, "touchcancel", cleanup, this);

      function ontouchend(event) {
        this.dragend(event, event.target);
        cleanup();
      }
      function cleanup() {
        log("cleanup");
        this.touchPositions = {};
        this.el = this.dragData = null;
        return [move, end, cancel].forEach(function(handler) {
          return handler.off();
        });
      }
    },
    move: function(event) {
      var deltas = { x: [], y: [] };

      [].forEach.call(event.changedTouches,function(touch, index) {
        var lastPosition = this.touchPositions[index];
        if (lastPosition) {
          deltas.x.push(touch.pageX - lastPosition.x);
          deltas.y.push(touch.pageY - lastPosition.y);
        } else {
          this.touchPositions[index] = lastPosition = {};
        }
        lastPosition.x = touch.pageX;
        lastPosition.y = touch.pageY;
      }.bind(this))

      this.elTranslation.x += average(deltas.x);
      this.elTranslation.y += average(deltas.y);
      this.el.style["z-index"] = "999999";
      this.el.style["pointer-events"] = "none";
      writeTransform(this.el, this.elTranslation.x, this.elTranslation.y);

      this.synthesizeEnterLeave(event);
    },
    synthesizeEnterLeave: function(event) {
      var target = elementFromTouchEvent(this.el,event)
      if (target != this.lastEnter) {
        if (this.lastEnter) {
          this.dispatchLeave();
        }
        this.lastEnter = target;
        this.dispatchEnter();
      }
    },
    dragend: function(event) {

      // we'll dispatch drop if there's a target, then dragEnd. If drop isn't fired
      // or isn't cancelled, we'll snap back
      // drop comes first http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
      log("dragend");

      if (this.lastEnter) {
        this.dispatchLeave();
      }

      var target = elementFromTouchEvent(this.el,event)

      if (target) {
        log("found drop target " + target.tagName);
        this.dispatchDrop(target)
      } else {
        log("no drop target, scheduling snapBack")
        once(doc, "dragend", this.snapBack, this);
      }

      var dragendEvt = doc.createEvent("Event");
      dragendEvt.initEvent("dragend", true, true);
      this.el.dispatchEvent(dragendEvt);
    },
    dispatchDrop: function(target) {
      var snapBack = true;

      var dropEvt = doc.createEvent("Event");
      dropEvt.initEvent("drop", true, true);
      dropEvt.dataTransfer = {
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };
      dropEvt.preventDefault = function() {
         // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14638 - if we don't cancel it, we'll snap back
        this.el.style["z-index"] = "";
        this.el.style["pointer-events"] = "auto";
        snapBack = false;
        writeTransform(this.el, 0, 0);
      }.bind(this);

      once(doc, "drop", function() {
        log("drop event not canceled");
        if (snapBack) this.snapBack()
      },this);

      target.dispatchEvent(dropEvt);
    },
    dispatchEnter: function() {

      var enterEvt = doc.createEvent("Event");
      enterEvt.initEvent("dragenter", true, true);
      enterEvt.dataTransfer = {
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      this.lastEnter.dispatchEvent(enterEvt);
    },
    dispatchLeave: function() {

      var leaveEvt = doc.createEvent("Event");
      leaveEvt.initEvent("dragleave", true, true);
      leaveEvt.dataTransfer = {
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      this.lastEnter.dispatchEvent(leaveEvt);
      this.lastEnter = null;
    },
    snapBack: function() {
      once(this.el, "webkitTransitionEnd", function() {
        this.el.style["pointer-events"] = "auto";
        this.el.style["z-index"] = "";
        this.el.style["-webkit-transition"] = "none";
      },this);
      setTimeout(function() {
        this.el.style["-webkit-transition"] = "all 0.2s";
        writeTransform(this.el, 0, 0)
      }.bind(this));
    },
    dispatchDragStart: function() {
      var evt = doc.createEvent("Event");
      evt.initEvent("dragstart", true, true);
      evt.dataTransfer = {
        setData: function(type, val) {
          this.dragData[type] = val;
          return val;
        }.bind(this),
        dropEffect: "move"
      };
      this.el.dispatchEvent(evt);
    }
  }

  // event listeners
  function touchstart(evt) {
    var el = evt.target;
    do {
      if (el.hasAttribute("draggable")) {
        evt.preventDefault();
        new DragDrop(evt,el);
      }
    } while((el = el.parentNode) && el !== doc.body)
  }

  // DOM helpers
  function elementFromTouchEvent(el,event) {
    var touch = event.changedTouches[0];
    var target = doc.elementFromPoint(
      touch[coordinateSystemForElementFromPoint + "X"],
      touch[coordinateSystemForElementFromPoint + "Y"]
    );
    return target
  }

  function readTransform(el) {
    var transform = el.style["-webkit-transform"];
    var x = 0
    var y = 0
    var match = /translate\(\s*(\d+)[^,]*,\D*(\d+)/.exec(transform)
    if(match) {
      x = parseInt(match[1],10)
      y = parseInt(match[2],10)
    }
    return { x: x, y: y };
  }

  function writeTransform(el, x, y) {
    var transform = el.style["-webkit-transform"].replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g, '');
    el.style["-webkit-transform"] = transform + " translate(" + x + "px," + y + "px)";
  }

  function onEvt(el, event, handler, context) {
    if(context) handler = handler.bind(context)
    el.addEventListener(event, handler);
    return {
      off: function() {
        return el.removeEventListener(event, handler);
      }
    };
  }

  function once(el, event, handler, context) {
    if(context) handler = handler.bind(context)
    function listener(evt) {
      handler(evt);
      return el.removeEventListener(event,listener);
    }
    return el.addEventListener(event,listener);
  }

  // general helpers
  function log(msg) {
    console.log(msg);
  }

  function average(arr) {
    if (arr.length === 0) return 0;
    return arr.reduce((function(s, v) {
      return v + s;
    }), 0) / arr.length;
  }

  function noop() {}

  main(window.iosDragDropShim);

})(document);
<commit_msg>Add drop target location<commit_after>(function(doc) {

  log = noop; // noOp, remove this line to enable debugging

  var coordinateSystemForElementFromPoint;

  function main(config) {
    config = config || {};

    coordinateSystemForElementFromPoint = navigator.userAgent.match(/OS 5(?:_\d+)+ like Mac/) ? "client" : "page";

    var div = doc.createElement('div');
    var dragDiv = 'draggable' in div;
    var evts = 'ondragstart' in div && 'ondrop' in div;

    var needsPatch = !(dragDiv || evts) || /iPad|iPhone|iPod/.test(navigator.userAgent);
    log((needsPatch ? "" : "not ") + "patching html5 drag drop");

    if(!needsPatch) return;

    if(!config.enableEnterLeave) {
      DragDrop.prototype.synthesizeEnterLeave = noop;
    }

    doc.addEventListener("touchstart", touchstart);
  }

  function DragDrop(event, el) {

    this.touchPositions = {};
    this.dragData = {};
    this.el = el || event.target

    event.preventDefault();

    log("dragstart");

    this.dispatchDragStart()
    this.elTranslation = readTransform(this.el);

    this.listen()

  }

  DragDrop.prototype = {
    listen: function() {
      var move = onEvt(doc, "touchmove", this.move, this);
      var end = onEvt(doc, "touchend", ontouchend, this);
      var cancel = onEvt(doc, "touchcancel", cleanup, this);

      function ontouchend(event) {
        this.dragend(event, event.target);
        cleanup();
      }
      function cleanup() {
        log("cleanup");
        this.touchPositions = {};
        this.el = this.dragData = null;
        return [move, end, cancel].forEach(function(handler) {
          return handler.off();
        });
      }
    },
    move: function(event) {
      var deltas = { x: [], y: [] };

      [].forEach.call(event.changedTouches,function(touch, index) {
        var lastPosition = this.touchPositions[index];
        if (lastPosition) {
          deltas.x.push(touch.pageX - lastPosition.x);
          deltas.y.push(touch.pageY - lastPosition.y);
        } else {
          this.touchPositions[index] = lastPosition = {};
        }
        lastPosition.x = touch.pageX;
        lastPosition.y = touch.pageY;
      }.bind(this))

      this.elTranslation.x += average(deltas.x);
      this.elTranslation.y += average(deltas.y);
      this.el.style["z-index"] = "999999";
      this.el.style["pointer-events"] = "none";
      writeTransform(this.el, this.elTranslation.x, this.elTranslation.y);

      this.synthesizeEnterLeave(event);
    },
    synthesizeEnterLeave: function(event) {
      var target = elementFromTouchEvent(this.el,event)
      if (target != this.lastEnter) {
        if (this.lastEnter) {
          this.dispatchLeave();
        }
        this.lastEnter = target;
        this.dispatchEnter();
      }
    },
    dragend: function(event) {

      // we'll dispatch drop if there's a target, then dragEnd. If drop isn't fired
      // or isn't cancelled, we'll snap back
      // drop comes first http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
      log("dragend");

      if (this.lastEnter) {
        this.dispatchLeave();
      }

      var target = elementFromTouchEvent(this.el,event)

      if (target) {
        log("found drop target " + target.tagName);
        this.dispatchDrop(target, event)
      } else {
        log("no drop target, scheduling snapBack")
        once(doc, "dragend", this.snapBack, this);
      }

      var dragendEvt = doc.createEvent("Event");
      dragendEvt.initEvent("dragend", true, true);
      this.el.dispatchEvent(dragendEvt);
    },
    dispatchDrop: function(target, event) {
      var snapBack = true;

      var dropEvt = doc.createEvent("Event");
      dropEvt.initEvent("drop", true, true);

      var x = event[coordinateSystemForElementFromPoint + 'X'];
      var y = event[coordinateSystemForElementFromPoint + 'Y'];
      dropEvt.offsetX = target.x - x;
      dropEvt.offsetY = target.y - y;

      dropEvt.dataTransfer = {
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };
      dropEvt.preventDefault = function() {
         // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14638 - if we don't cancel it, we'll snap back
        this.el.style["z-index"] = "";
        this.el.style["pointer-events"] = "auto";
        snapBack = false;
        writeTransform(this.el, 0, 0);
      }.bind(this);

      once(doc, "drop", function() {
        log("drop event not canceled");
        if (snapBack) this.snapBack()
      },this);

      target.dispatchEvent(dropEvt);
    },
    dispatchEnter: function() {

      var enterEvt = doc.createEvent("Event");
      enterEvt.initEvent("dragenter", true, true);
      enterEvt.dataTransfer = {
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      this.lastEnter.dispatchEvent(enterEvt);
    },
    dispatchLeave: function() {

      var leaveEvt = doc.createEvent("Event");
      leaveEvt.initEvent("dragleave", true, true);
      leaveEvt.dataTransfer = {
        getData: function(type) {
          return this.dragData[type];
        }.bind(this)
      };

      this.lastEnter.dispatchEvent(leaveEvt);
      this.lastEnter = null;
    },
    snapBack: function() {
      once(this.el, "webkitTransitionEnd", function() {
        this.el.style["pointer-events"] = "auto";
        this.el.style["z-index"] = "";
        this.el.style["-webkit-transition"] = "none";
      },this);
      setTimeout(function() {
        this.el.style["-webkit-transition"] = "all 0.2s";
        writeTransform(this.el, 0, 0)
      }.bind(this));
    },
    dispatchDragStart: function() {
      var evt = doc.createEvent("Event");
      evt.initEvent("dragstart", true, true);
      evt.dataTransfer = {
        setData: function(type, val) {
          this.dragData[type] = val;
          return val;
        }.bind(this),
        dropEffect: "move"
      };
      this.el.dispatchEvent(evt);
    }
  }

  // event listeners
  function touchstart(evt) {
    var el = evt.target;
    do {
      if (el.hasAttribute("draggable")) {
        evt.preventDefault();
        new DragDrop(evt,el);
      }
    } while((el = el.parentNode) && el !== doc.body)
  }

  // DOM helpers
  function elementFromTouchEvent(el,event) {
    var touch = event.changedTouches[0];
    var target = doc.elementFromPoint(
      touch[coordinateSystemForElementFromPoint + "X"],
      touch[coordinateSystemForElementFromPoint + "Y"]
    );
    return target
  }

  function readTransform(el) {
    var transform = el.style["-webkit-transform"];
    var x = 0
    var y = 0
    var match = /translate\(\s*(\d+)[^,]*,\D*(\d+)/.exec(transform)
    if(match) {
      x = parseInt(match[1],10)
      y = parseInt(match[2],10)
    }
    return { x: x, y: y };
  }

  function writeTransform(el, x, y) {
    var transform = el.style["-webkit-transform"].replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g, '');
    el.style["-webkit-transform"] = transform + " translate(" + x + "px," + y + "px)";
  }

  function onEvt(el, event, handler, context) {
    if(context) handler = handler.bind(context)
    el.addEventListener(event, handler);
    return {
      off: function() {
        return el.removeEventListener(event, handler);
      }
    };
  }

  function once(el, event, handler, context) {
    if(context) handler = handler.bind(context)
    function listener(evt) {
      handler(evt);
      return el.removeEventListener(event,listener);
    }
    return el.addEventListener(event,listener);
  }

  // general helpers
  function log(msg) {
    console.log(msg);
  }

  function average(arr) {
    if (arr.length === 0) return 0;
    return arr.reduce((function(s, v) {
      return v + s;
    }), 0) / arr.length;
  }

  function noop() {}

  main(window.iosDragDropShim);

})(document);
<|endoftext|>


<commit_before>// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// We use this code for handling unexpected errors.
// Using JS confirm function we are sure that the user get notified in a Mobile device.
// This script should be added at the begining of the index.html and it should only use native javascript functions.

var appVersion = '3.1.2 (2014)',
    reportInBackgroundName = 'mmCoreReportInBackground',
    errors = [],
    ignoredFiles = ['www/index.html#/site/mod_page', 'www/index.html#/site/mod_resource', 'www/index.html#/site/mm_course-section'];

/**
 * Check if error should be reported in background. If setting is not set, a confirm modal will be shown.
 *
 * @return {Boolean} True if should be reported in background, false otherwise.
 */
function shouldReportInBackground() {
    var inBackground = false,
        flag;

    if (localStorage && localStorage.getItem && localStorage.setItem) {
        flag = localStorage.getItem(reportInBackgroundName);
        if (isNaN(parseInt(flag, 10))) {
            // Flag not set. Show a confirm modal.
            var confirmmsg = 'Do you want to report errors automatically? Reporting errors will help us fixing them. ' +
                                'You can change this setting in App Settings.';
            inBackground = confirm(confirmmsg);
            localStorage.setItem(reportInBackgroundName, inBackground ? '1' : '0');
        } else {
            inBackground = flag === '1';
        }
    }

    return inBackground;
}

window.onerror = function(msg, url, lineNumber) {
    try {
        var errorReported = false,
            reportedOnDBReady = false,
            reportInBackground = false;

        /**
         * Add the storage type to the error report and send it.
         *
         * @param  {String} reportUrl URL to report the error.
         * @param  {Object} db        DB.
         */
        function getStorageAndReport(reportUrl, db) {
            if (!reportedOnDBReady) {
                reportedOnDBReady = true;
                reportUrl = reportUrl + '&storage=' + encodeURIComponent(db.getType());
                sendError(reportUrl);
            }
        }

        /**
         * Gather the needed data to report an error and reports it.
         */
        function reportError() {
            if (!errorReported) {
                errorReported = true;
                var reportUrl = 'http://prototype.moodle.net/mobile/feedback/mmfeedback.php?message=' + encodeURIComponent(msg) +
                                '&file=' + encodeURIComponent(url) + '&line=' + encodeURIComponent(lineNumber) + '&appv=' +
                                encodeURIComponent(appVersion) + '&bg=' + (reportInBackground ? 1 : 0);

                if (window.device) {
                    reportUrl = reportUrl + '&platform=' + encodeURIComponent(window.device.platform) +
                                        '&model=' + encodeURIComponent(window.device.model) +
                                        '&osversion=' + encodeURIComponent(window.device.version) +
                                        '&cordova=' + encodeURIComponent(window.device.cordova);
                }
                if (window.location) {
                    reportUrl = reportUrl + '&localurl=' + encodeURIComponent(window.location.href);
                }
                if (navigator.userAgent) {
                    reportUrl = reportUrl + '&useragent=' + encodeURIComponent(navigator.userAgent);
                }
                if (typeof ydn != 'undefined' && ydn.db && ydn.db.Storage) {
                    // Detect Storage type by default.
                    var db = new ydn.db.Storage('test', {}, {});
                    if (db && db.getType && db.onReady) {
                        db.onReady(function() {
                            getStorageAndReport(reportUrl, db);
                        });
                        setTimeout(function() {
                            getStorageAndReport(reportUrl, db);
                        }, 1000);
                        return;
                    }
                }

                sendError(reportUrl);
            }
        }

        /**
         * Send error to the server.
         *
         * @param  {String} reportUrl URL to report the error.
         */
        function sendError(reportUrl) {
            if (reportInBackground) {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', reportUrl, true);
                xhr.send();
            } else {
                window.open(reportUrl, '_system');
            }
        }

        /**
         * Check if an error should be ignored.
         *
         * @return {Boolean} True if error should be ignored, false otherwise.
         */
        function shouldBeIgnored() {
            for (var i = 0; i < ignoredFiles.length; i++) {
                if (url.indexOf(ignoredFiles[i]) > -1) {
                    return true;
                }
            }
            return false;
        }

        if (errors.indexOf(msg) == -1 && !shouldBeIgnored()) {
            // Error hasn't happened yet.
            errors.push(msg);
            reportInBackground = shouldReportInBackground();

            // Use setTimeout to prevent the following error if the app crashes right at the start:
            // "The connection to the server was unsuccessful. (file:///android_asset/www/index.html)"
            setTimeout(function() {
                if (typeof msg == "string") {
                    var send = true,
                        confirmmsg = 'Unexpected error, please accept to report the bug so we can work on fixing it ' +
                                        '(Internet connection required).';

                    if (!reportInBackground) {
                        send = confirm(confirmmsg);
                    }

                    if (send) {
                        // Wait for device ready so we can retrieve device data. In most cases device will already be ready.
                        document.addEventListener('deviceready', reportError);
                        // Report error if device ready isn't fired after 5 seconds.
                        setTimeout(reportError, 5000);
                    }
                }
            }, 100);
        }

        // This may help debugging if we use logging apps in iOs or Android.
        if (typeof console != "undefined" && typeof console.log == "function") {
            console.log(msg);
        }
    } catch(ex) {
        // Something bad happened.
    }

    // Let default error handler run.
    return false;
};
<commit_msg>Update errorreport.js<commit_after>// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// We use this code for handling unexpected errors.
// Using JS confirm function we are sure that the user get notified in a Mobile device.
// This script should be added at the begining of the index.html and it should only use native javascript functions.

var appVersion = '3.1.2 (2014)',
    reportInBackgroundName = 'mmCoreReportInBackground',
    errors = [],
    ignoredFiles = ['www/index.html#/site/mod_page', 'www/index.html#/site/mod_resource', 'www/index.html#/site/mm_course-section'];

/**
 * Check if error should be reported in background. If setting is not set, a confirm modal will be shown.
 *
 * @return {Boolean} True if should be reported in background, false otherwise.
 */
function shouldReportInBackground() {
    var inBackground = false,
        flag;

    if (localStorage && localStorage.getItem && localStorage.setItem) {
        flag = localStorage.getItem(reportInBackgroundName);
        if (isNaN(parseInt(flag, 10))) {
            // Flag not set. Show a confirm modal.
            var confirmmsg = 'Do you want to report errors automatically? Reporting errors will help us fixing them. ' +
                                'You can change this setting in App Settings.';
            inBackground = confirm(confirmmsg);
            localStorage.setItem(reportInBackgroundName, inBackground ? '1' : '0');
        } else {
            inBackground = flag === '1';
        }
    }

    return inBackground;
}

window.onerror = function(msg, url, lineNumber) {
    try {
        var errorReported = false,
            reportedOnDBReady = false,
            reportInBackground = false;

        /**
         * Add the storage type to the error report and send it.
         *
         * @param  {String} reportUrl URL to report the error.
         * @param  {Object} db        DB.
         */
        function getStorageAndReport(reportUrl, db) {
            if (!reportedOnDBReady) {
                reportedOnDBReady = true;
                reportUrl = reportUrl + '&storage=' + encodeURIComponent(db.getType());
                sendError(reportUrl);
            }
        }

        /**
         * Gather the needed data to report an error and reports it.
         */
        function reportError() {
            if (!errorReported) {
                errorReported = true;
                var reportUrl = 'http://www.jaihindiasacademy.com/portal/mobile/feedback/mmfeedback.php?message=' + encodeURIComponent(msg) +
                                '&file=' + encodeURIComponent(url) + '&line=' + encodeURIComponent(lineNumber) + '&appv=' +
                                encodeURIComponent(appVersion) + '&bg=' + (reportInBackground ? 1 : 0);

                if (window.device) {
                    reportUrl = reportUrl + '&platform=' + encodeURIComponent(window.device.platform) +
                                        '&model=' + encodeURIComponent(window.device.model) +
                                        '&osversion=' + encodeURIComponent(window.device.version) +
                                        '&cordova=' + encodeURIComponent(window.device.cordova);
                }
                if (window.location) {
                    reportUrl = reportUrl + '&localurl=' + encodeURIComponent(window.location.href);
                }
                if (navigator.userAgent) {
                    reportUrl = reportUrl + '&useragent=' + encodeURIComponent(navigator.userAgent);
                }
                if (typeof ydn != 'undefined' && ydn.db && ydn.db.Storage) {
                    // Detect Storage type by default.
                    var db = new ydn.db.Storage('test', {}, {});
                    if (db && db.getType && db.onReady) {
                        db.onReady(function() {
                            getStorageAndReport(reportUrl, db);
                        });
                        setTimeout(function() {
                            getStorageAndReport(reportUrl, db);
                        }, 1000);
                        return;
                    }
                }

                sendError(reportUrl);
            }
        }

        /**
         * Send error to the server.
         *
         * @param  {String} reportUrl URL to report the error.
         */
        function sendError(reportUrl) {
            if (reportInBackground) {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', reportUrl, true);
                xhr.send();
            } else {
                window.open(reportUrl, '_system');
            }
        }

        /**
         * Check if an error should be ignored.
         *
         * @return {Boolean} True if error should be ignored, false otherwise.
         */
        function shouldBeIgnored() {
            for (var i = 0; i < ignoredFiles.length; i++) {
                if (url.indexOf(ignoredFiles[i]) > -1) {
                    return true;
                }
            }
            return false;
        }

        if (errors.indexOf(msg) == -1 && !shouldBeIgnored()) {
            // Error hasn't happened yet.
            errors.push(msg);
            reportInBackground = shouldReportInBackground();

            // Use setTimeout to prevent the following error if the app crashes right at the start:
            // "The connection to the server was unsuccessful. (file:///android_asset/www/index.html)"
            setTimeout(function() {
                if (typeof msg == "string") {
                    var send = true,
                        confirmmsg = 'Unexpected error, please accept to report the bug so we can work on fixing it ' +
                                        '(Internet connection required).';

                    if (!reportInBackground) {
                        send = confirm(confirmmsg);
                    }

                    if (send) {
                        // Wait for device ready so we can retrieve device data. In most cases device will already be ready.
                        document.addEventListener('deviceready', reportError);
                        // Report error if device ready isn't fired after 5 seconds.
                        setTimeout(reportError, 5000);
                    }
                }
            }, 100);
        }

        // This may help debugging if we use logging apps in iOs or Android.
        if (typeof console != "undefined" && typeof console.log == "function") {
            console.log(msg);
        }
    } catch(ex) {
        // Something bad happened.
    }

    // Let default error handler run.
    return false;
};
<|endoftext|>