<commit_before>var widgetModule = angular.module('widget', ['ngCookies']);

widgetModule.controller('widgetCtrl', function ($scope, $timeout, widgetService, mixpanelService, paramsService, dbService) {

    var hpcloud = 'HP';
    var softlayer = 'SOFTLAYER';
    var play = 'RUNNING';
    var stop = 'STOPPED';

    $scope.widgetStatus = {};

    function _getAdvanced(){
        return $scope.advancedParams[$scope.cloudType];
    }

    $scope.advancedParams = {};
    $scope.advancedParams[hpcloud] = {'type':'hpcloud-compute','params':{'project':null, 'key':null, 'secretKey':null}};
    $scope.advancedParams[softlayer] = {'type':'softlayer', 'params' : {'username':null, 'apiKey':null} };

    $scope.poweredByUrl = {};
    $scope.poweredByUrl[hpcloud] = "http://hpcloud.com";
    $scope.poweredByUrl[softlayer] = "http://softlayer.com";

    function _hasAdvanced(){
        var aData = _getAdvanced();
        var params = aData.params;
        for ( var i in params ){
            if ( params.hasOwnProperty(i) && !params[i] ){
                return false;
            }
        }
        return true;
    }

    function resetWidgetStatus( msg ){
        $scope.widgetStatus = {
            'state' : stop,
            'reset':true
        };

        if ( !!msg ){
            $scope.widgetStatus.message = msg;
        }
        ellipsisIndex = 0;
    }

    var ellipsisIndex = 0;
    var ellipsis='......';

    function _scrollLog() {
        var log = $('#log')[0];
        log.scrollTop = log.scrollHeight;
    }

    function handleStatus( status, myTimeout ){

        console.log(['got status', status]);
        dbService.saveWidgetStatus( status );
        $scope.ellipsis = ellipsis.substring(ellipsis.length - ellipsisIndex % ellipsis.length);
        ellipsisIndex = ellipsisIndex +1;
        $scope.widgetStatus = status;
        $timeout(pollStatus, myTimeout || 3000) ;
        _scrollLog();

    }

    function pollStatus( myTimeout){

        if ( $scope.widgetStatus.state !== stop ){ // keep polling until widget stops ==> mainly for timeleft..
            widgetService.getStatus( $scope.widgetStatus.instanceId, $scope.params.apiKey ).then( function( result ){
                if ( !result ){
                    return ;
                }
                handleStatus( result.status, myTimeout );
            },function(result){
                    console.log(['status error',result]);
                });
        }else{
            console.log("removing widget status");
            dbService.remove();
        }
    }

    $scope.isCompleted = function(){
        return $scope.widgetStatus.state === stop && !$scope.widgetStatus.instanceId && !$scope.widgetStatus.message && $scope.widgetStatus.timeleftMillis === 0;
    };
    $scope.pendingOutput = function(){
        return $scope.widgetStatus.state == play && !$scope.widgetStatus.output;
    };

    $scope.play = function(){
        resetWidgetStatus();
        $scope.widgetStatus.state = play;
        widgetService.play(  $scope.params.apiKey,  _hasAdvanced() ? _getAdvanced() : null )
            .then(function( result ){
                console.log(['play result', result]);
                $scope.widgetStatus = result.status;

                pollStatus(1);
        }, function( result ){
                console.log(['play error', result]);
                resetWidgetStatus("unknown error");
            });
//        success: function (data, textStatus, jqXHR) {
//            var state = data.status.state.toLowerCase();
//            if (state == "error" || state == "stopped") {
//                widgetState.showPlayButton();
//                widgetLog.error(data.status.message);
//                return;
//            }
//            if (data.status.instanceId) {
//                widgetState.instanceId(data.status.instanceId);
//            }
//
//            if ( advancedDataAvailable( advancedData ) ){
//                if (advancedData.project == advancedCookie.project() &&
//                    advancedData.key == advancedCookie.key() &&
//                    advancedData.secretKey == advancedCookie.secretKey()) {
//
//                    advancedCookie.prolong();
//
//                } else {
//                    $(".remember_creds").show();
//                }
//            }
//
//            setTimeoutForUpdateStatus(1);
//        },
//        error: function (data) {
//            var displayMessage = data.getResponseHeader("display-message");
//            if (displayMessage) {
//                var displayMessageObj = JSON.parse(displayMessage);
//                widgetLog.error(displayMessageObj.msg);
//            }
//        }
    };

    $scope.stop = function(){
        $scope.widgetStatus.state = stop;
        resetWidgetStatus();
    };

    $scope.getTimeLeft = function(){
        if ( !$scope.widgetStatus || !$scope.widgetStatus.timeleftMillis ){
            return "";
        }
        var timeLeft = $scope.widgetStatus.timeleftMillis;
        if ( !!timeLeft ){
            timeLeft = timeLeft / 1000;
            return (parseInt(timeLeft /60 ) + 1 )+ " minutes";
        }
        return "";
    };

    $scope.showPlay = function(){
        return $scope.widgetStatus.state === stop;
    };

    $scope.showStop = function(){
        return $scope.widgetStatus.state === play;
    };

    $scope.submitAdvancedData = function(){
        console.log("submitting advanced");
        $scope.play();
    };

    var savedStatus = dbService.getWidgetStatus();

    if ( !!savedStatus ){
        handleStatus( savedStatus,1 );
    }else{
        resetWidgetStatus();
    }

    console.log(["saved status", savedStatus]);
    // place params on scope
    $scope.params = paramsService.params;
    $scope.cloudType = myConf.cloudProvider;

    $scope.isShowAdvanced = function () {
        console.log(["showadvanced param is ", $scope.params.showAdvanced, $scope.params.showAdvanced == "true"]);
        try {
            return $scope.params.showAdvanced == "true";
        } catch (e) {
            return true;
        }
    };

    var apiKey = $scope.params.apiKey;
    var shareUrl= encodeURI("http://bluforcloud.com/plans/play");

    var msg =  encodeURI("Launch on the cloud in a single click using the Cloudify widget");
    var twitterMsg = encodeURIComponent( "I just installed #bluforcloud with a single click on http://bluforcloud.com/plans/play");

    $("#facebook_share_link").attr("href", "http://www.facebook.com/sharer/sharer.php?u=" + shareUrl).click(function(){
        window.open('http://www.facebook.com/sharer/sharer.php?u=' + shareUrl, 'facebook_share', 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
        return false;
    });
    $("#google_plus_share_link").attr("href", "https://plus.google.com/share?url=" + shareUrl).click(function(){
        window.open("https://plus.google.com/share?url=" + shareUrl, 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
    });
    $("#twitter_share_link").attr("href", "https://twitter.com/share?url=" + encodeURIComponent($scope.params.origin_page_url) + "&text=" + twitterMsg).click(function(){
        window.open("https://twitter.com/share?url=" + encodeURIComponent($scope.params.origin_page_url) + "&text=" + twitterMsg, 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
    });

});

// encrypt decrypt service
widgetModule.service('encryptDecrypt', function ($http) {
    this.encrypt = function (data) {
        return $http.post('/encrypt', {data: data });
    };

    this.decrypt = function (data) {
        return $http.post('/decrypt', {data: data})
    };
});

widgetModule.service('paramsService', function(){
    // read params from URL;
    function get_params() {
        var params = {};
        var hash;
        var hashes = window.location.search.substring(1).split('&');
        console.log(["using search tearm", hashes ]);
        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            if ($.trim(hash[1]) != ""){
                params[hash[0]] = decodeURIComponent(hash[1]);
            }
        }
        console.log(["params are",params]);
        return params;
    }

    this.params = get_params();
});

widgetModule.service('dbService', function( $cookieStore, paramsService ){

    var params = paramsService.params;

    function getCookieName(){
        return "widgetCookie" + params.origin_page_url + params.apiKey;
    }

    this.remove = function(){
        this.saveWidgetStatus(null);
    };

    this.saveWidgetStatus = function(status){
        if ( !status ){
           $cookieStore.remove( getCookieName() );
        }else{
            $cookieStore.put( getCookieName() , status);
        }
    };

    this.getWidgetStatus = function(){
        return $cookieStore.get( getCookieName() );
    }
});

widgetModule.service('advancedData', function (encryptDecrypt) {
    var cookieName = "ADVANCED_DATA";
    this.save = function (data) {
        encryptDecrypt.encrypt(data).then(function (result) {
            $.cookie(cookieName, JSON.stringify(data), {"path": "/", expires: 10000 });
        });
    };

    this.load = function () {

        encryptDecrypt.decrypt($.cookie(cookieName)).then(function (result) {
            return result.data
        });
    }
});

widgetModule.service('widgetService', function( $http, mixpanelService, paramsService ){
    var origin_page_url = paramsService.params.origin_page_url;
    this.getStatus = function( instanceId , apiKey ){
        return $http.get( "/widget/"+ instanceId + "/status?apiKey=" + apiKey).then( function( data ){
            $.postMessage( JSON.stringify({name:"widget_status", data:data.data}), origin_page_url , parent );
            return data.data;
        });
    };

    this.play = function( apiKey, advancedData ){
        $.postMessage( JSON.stringify({name:"play_widget"}), origin_page_url , parent );
        if ( !advancedData ){
            return $http.post( '/widget/start?apiKey=' + encodeURI(apiKey)).then(function(result){ return result.data; });
        }else{
            return $http.post( '/widget/start?apiKey=' + encodeURI(apiKey),advancedData).then(function(result){ return result.data});
        }

    };

    this.stop = function(){
        if (!confirm("Are you sure you want to stop the instance?")) {
            return;
        }
        mixpanelService.stopWidget();
        $.postMessage( JSON.stringify({name:"stop_widget"}), origin_page_url , parent );
        widgetState.showPlayButton();
        if ( widgetState.instanceId()) {
            $.post("/widget/"+ widgetState.instanceId() + "/stop?apiKey=" + params["apiKey"], {}, function (data) {
                if (data && data.status && data.status.state == "error") {
                    widgetState.showPlayButton();
                    widgetLog.error(data.status.message );
                    return;
                }
                stop_instance();
            });
        }
    }
});

widgetModule.service('mixpanelService', function( paramsService){
    var params = paramsService.params;
      this.stopWidget = function(){
            mixpanel.track("Stop Widget",{'page name' : params.title, 'url' : params.origin_page_url });
      };
});

<commit_msg>fixing twitter message.<commit_after>var widgetModule = angular.module('widget', ['ngCookies']);

widgetModule.controller('widgetCtrl', function ($scope, $timeout, widgetService, mixpanelService, paramsService, dbService) {

    var hpcloud = 'HP';
    var softlayer = 'SOFTLAYER';
    var play = 'RUNNING';
    var stop = 'STOPPED';

    $scope.widgetStatus = {};

    function _getAdvanced(){
        return $scope.advancedParams[$scope.cloudType];
    }

    $scope.advancedParams = {};
    $scope.advancedParams[hpcloud] = {'type':'hpcloud-compute','params':{'project':null, 'key':null, 'secretKey':null}};
    $scope.advancedParams[softlayer] = {'type':'softlayer', 'params' : {'username':null, 'apiKey':null} };

    $scope.poweredByUrl = {};
    $scope.poweredByUrl[hpcloud] = "http://hpcloud.com";
    $scope.poweredByUrl[softlayer] = "http://softlayer.com";

    function _hasAdvanced(){
        var aData = _getAdvanced();
        var params = aData.params;
        for ( var i in params ){
            if ( params.hasOwnProperty(i) && !params[i] ){
                return false;
            }
        }
        return true;
    }

    function resetWidgetStatus( msg ){
        $scope.widgetStatus = {
            'state' : stop,
            'reset':true
        };

        if ( !!msg ){
            $scope.widgetStatus.message = msg;
        }
        ellipsisIndex = 0;
    }

    var ellipsisIndex = 0;
    var ellipsis='......';

    function _scrollLog() {
        var log = $('#log')[0];
        log.scrollTop = log.scrollHeight;
    }

    function handleStatus( status, myTimeout ){

        console.log(['got status', status]);
        dbService.saveWidgetStatus( status );
        $scope.ellipsis = ellipsis.substring(ellipsis.length - ellipsisIndex % ellipsis.length);
        ellipsisIndex = ellipsisIndex +1;
        $scope.widgetStatus = status;
        $timeout(pollStatus, myTimeout || 3000) ;
        _scrollLog();

    }

    function pollStatus( myTimeout){

        if ( $scope.widgetStatus.state !== stop ){ // keep polling until widget stops ==> mainly for timeleft..
            widgetService.getStatus( $scope.widgetStatus.instanceId, $scope.params.apiKey ).then( function( result ){
                if ( !result ){
                    return ;
                }
                handleStatus( result.status, myTimeout );
            },function(result){
                    console.log(['status error',result]);
                });
        }else{
            console.log("removing widget status");
            dbService.remove();
        }
    }

    $scope.isCompleted = function(){
        return $scope.widgetStatus.state === stop && !$scope.widgetStatus.instanceId && !$scope.widgetStatus.message && $scope.widgetStatus.timeleftMillis === 0;
    };
    $scope.pendingOutput = function(){
        return $scope.widgetStatus.state == play && !$scope.widgetStatus.output;
    };

    $scope.play = function(){
        resetWidgetStatus();
        $scope.widgetStatus.state = play;
        widgetService.play(  $scope.params.apiKey,  _hasAdvanced() ? _getAdvanced() : null )
            .then(function( result ){
                console.log(['play result', result]);
                $scope.widgetStatus = result.status;

                pollStatus(1);
        }, function( result ){
                console.log(['play error', result]);
                resetWidgetStatus("unknown error");
            });
//        success: function (data, textStatus, jqXHR) {
//            var state = data.status.state.toLowerCase();
//            if (state == "error" || state == "stopped") {
//                widgetState.showPlayButton();
//                widgetLog.error(data.status.message);
//                return;
//            }
//            if (data.status.instanceId) {
//                widgetState.instanceId(data.status.instanceId);
//            }
//
//            if ( advancedDataAvailable( advancedData ) ){
//                if (advancedData.project == advancedCookie.project() &&
//                    advancedData.key == advancedCookie.key() &&
//                    advancedData.secretKey == advancedCookie.secretKey()) {
//
//                    advancedCookie.prolong();
//
//                } else {
//                    $(".remember_creds").show();
//                }
//            }
//
//            setTimeoutForUpdateStatus(1);
//        },
//        error: function (data) {
//            var displayMessage = data.getResponseHeader("display-message");
//            if (displayMessage) {
//                var displayMessageObj = JSON.parse(displayMessage);
//                widgetLog.error(displayMessageObj.msg);
//            }
//        }
    };

    $scope.stop = function(){
        $scope.widgetStatus.state = stop;
        resetWidgetStatus();
    };

    $scope.getTimeLeft = function(){
        if ( !$scope.widgetStatus || !$scope.widgetStatus.timeleftMillis ){
            return "";
        }
        var timeLeft = $scope.widgetStatus.timeleftMillis;
        if ( !!timeLeft ){
            timeLeft = timeLeft / 1000;
            return (parseInt(timeLeft /60 ) + 1 )+ " minutes";
        }
        return "";
    };

    $scope.showPlay = function(){
        return $scope.widgetStatus.state === stop;
    };

    $scope.showStop = function(){
        return $scope.widgetStatus.state === play;
    };

    $scope.submitAdvancedData = function(){
        console.log("submitting advanced");
        $scope.play();
    };

    var savedStatus = dbService.getWidgetStatus();

    if ( !!savedStatus ){
        handleStatus( savedStatus,1 );
    }else{
        resetWidgetStatus();
    }

    console.log(["saved status", savedStatus]);
    // place params on scope
    $scope.params = paramsService.params;
    $scope.cloudType = myConf.cloudProvider;

    $scope.isShowAdvanced = function () {
        console.log(["showadvanced param is ", $scope.params.showAdvanced, $scope.params.showAdvanced == "true"]);
        try {
            return $scope.params.showAdvanced == "true";
        } catch (e) {
            return true;
        }
    };

    var apiKey = $scope.params.apiKey;
    var shareUrl= encodeURI("http://bluforcloud.com/plans/play");

    var msg =  encodeURI("Launch on the cloud in a single click using the Cloudify widget");
    var twitterMsg = encodeURIComponent( "I just installed #bluforcloud with a single click");

    $("#facebook_share_link").attr("href", "http://www.facebook.com/sharer/sharer.php?u=" + shareUrl).click(function(){
        window.open('http://www.facebook.com/sharer/sharer.php?u=' + shareUrl, 'facebook_share', 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
        return false;
    });
    $("#google_plus_share_link").attr("href", "https://plus.google.com/share?url=" + shareUrl).click(function(){
        window.open("https://plus.google.com/share?url=" + shareUrl, 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
    });
    $("#twitter_share_link").attr("href", "https://twitter.com/share?url=" + encodeURIComponent($scope.params.origin_page_url) + "&text=" + twitterMsg).click(function(){
        window.open("https://twitter.com/share?url=" + encodeURIComponent($scope.params.origin_page_url) + "&text=" + twitterMsg, 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
    });

});

// encrypt decrypt service
widgetModule.service('encryptDecrypt', function ($http) {
    this.encrypt = function (data) {
        return $http.post('/encrypt', {data: data });
    };

    this.decrypt = function (data) {
        return $http.post('/decrypt', {data: data})
    };
});

widgetModule.service('paramsService', function(){
    // read params from URL;
    function get_params() {
        var params = {};
        var hash;
        var hashes = window.location.search.substring(1).split('&');
        console.log(["using search tearm", hashes ]);
        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            if ($.trim(hash[1]) != ""){
                params[hash[0]] = decodeURIComponent(hash[1]);
            }
        }
        console.log(["params are",params]);
        return params;
    }

    this.params = get_params();
});

widgetModule.service('dbService', function( $cookieStore, paramsService ){

    var params = paramsService.params;

    function getCookieName(){
        return "widgetCookie" + params.origin_page_url + params.apiKey;
    }

    this.remove = function(){
        this.saveWidgetStatus(null);
    };

    this.saveWidgetStatus = function(status){
        if ( !status ){
           $cookieStore.remove( getCookieName() );
        }else{
            $cookieStore.put( getCookieName() , status);
        }
    };

    this.getWidgetStatus = function(){
        return $cookieStore.get( getCookieName() );
    }
});

widgetModule.service('advancedData', function (encryptDecrypt) {
    var cookieName = "ADVANCED_DATA";
    this.save = function (data) {
        encryptDecrypt.encrypt(data).then(function (result) {
            $.cookie(cookieName, JSON.stringify(data), {"path": "/", expires: 10000 });
        });
    };

    this.load = function () {

        encryptDecrypt.decrypt($.cookie(cookieName)).then(function (result) {
            return result.data
        });
    }
});

widgetModule.service('widgetService', function( $http, mixpanelService, paramsService ){
    var origin_page_url = paramsService.params.origin_page_url;
    this.getStatus = function( instanceId , apiKey ){
        return $http.get( "/widget/"+ instanceId + "/status?apiKey=" + apiKey).then( function( data ){
            $.postMessage( JSON.stringify({name:"widget_status", data:data.data}), origin_page_url , parent );
            return data.data;
        });
    };

    this.play = function( apiKey, advancedData ){
        $.postMessage( JSON.stringify({name:"play_widget"}), origin_page_url , parent );
        if ( !advancedData ){
            return $http.post( '/widget/start?apiKey=' + encodeURI(apiKey)).then(function(result){ return result.data; });
        }else{
            return $http.post( '/widget/start?apiKey=' + encodeURI(apiKey),advancedData).then(function(result){ return result.data});
        }

    };

    this.stop = function(){
        if (!confirm("Are you sure you want to stop the instance?")) {
            return;
        }
        mixpanelService.stopWidget();
        $.postMessage( JSON.stringify({name:"stop_widget"}), origin_page_url , parent );
        widgetState.showPlayButton();
        if ( widgetState.instanceId()) {
            $.post("/widget/"+ widgetState.instanceId() + "/stop?apiKey=" + params["apiKey"], {}, function (data) {
                if (data && data.status && data.status.state == "error") {
                    widgetState.showPlayButton();
                    widgetLog.error(data.status.message );
                    return;
                }
                stop_instance();
            });
        }
    }
});

widgetModule.service('mixpanelService', function( paramsService){
    var params = paramsService.params;
      this.stopWidget = function(){
            mixpanel.track("Stop Widget",{'page name' : params.title, 'url' : params.origin_page_url });
      };
});

<|endoftext|>


<commit_before>
/*
All required uci packages are stored variable uci.
The GUI code displayes and manipulated this variable.
*/
var uci = {};
var gid = 0;

function init()
{
	send("/cgi-bin/settings", { func : "get_settings" }, function(data) {
		uci = fromUCI(data);
		rebuild_general();
	});
}

function updateFrom(src)
{
	var obj = {};
	collect_inputs(src, obj);
	for(var name in obj)
	{
		var value = obj[name];
		var path = name.split('#');

		var pkg = path[0];
		var sec = path[1];
		var opt = path[2];

		uci[pkg].pchanged = true;
		uci[pkg][sec][opt] = value
	}
}

function getChangeModeAction(ifname)
{
	return function(e) {
		var src = (e.target || e.srcElement);
		var mode = src.value;
		delNetSection(ifname);
		addNetSection(ifname, mode);
	};
}

function appendSetting(p, path, value, mode)
{
	var id = path.join('#');
	var b;
	var cfg = path[0]
	var name = path[path.length-1];
	switch(name)
	{
	case "geo":
		b = append_input(p, "GPS-Koordinaten", id, value);
		b.lastChild.placeholder = "52.02713078 8.52829987";
		addInputCheck(b.lastChild,/^\d{1,3}\.\d{1,8} +\d{1,3}\.\d{1,8}$/, "Koordinaten ist ung\xfcltig.");
		addHelpText(b, "Die Koordinaten dieses Knotens auf der Freifunk-Karte (z.B. \"52.02713078 8.52829987\").");
		break;
	case "name":
		b = append_input(p, "Knotenname", id, value);
		b.lastChild.placeholder = "MeinRouter";
		addInputCheck(b.lastChild,/^[\-\^'\w\.\:\[\]\(\)\/ \u0080-\u00FF]{0,32}$/, name + " ist ung\xfcltig.");
		addHelpText(b, "Der Name dieses Knotens auf der Freifunk-Karte.");
		break;
	case "enabled":
		if(cfg == "autoupdater") {
			b = append_radio(p, "Autoupdater", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Der Autoupdater aktualisiert die Firmware automatisch auf die neuste Version. Dabei werden allerdings alle Einstellungen zur\xfcckgesetzt.");
		}
		if(cfg == "simple-tc") {
			b = append_radio(p, "Bandweitenkontrolle", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Bandweitenkontrolle f\xfcr den Upload-/Download \xfcber das Freifunknetz \xfcber den eigenen Internetanschluss.");
		}
		break;
	case "map_publish":
		b = append_radio(p, "Zur Karte beitragen", id, value, [["Ja", "1"], ["Nein", "0"]]);
		addHelpText(b, "Soll dieser Knoten auf der Knotenkarte angezeigt werden?");
		break;
	case "limit_egress":
		b = append_input(p, "Public Upload", id, value);
		addInputCheck(b.lastChild,/^\d+$/, "Upload ist ung\xfcltig.");
		addHelpText(b, "Maximaler Upload in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "limit_ingress":
		b = append_input(p, "Public Download", id, value);
		addInputCheck(b.lastChild,/^\d+$/, "Download ist ung\xfcltig.");
		addHelpText(b, "Maximaler Download in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "access_from":
		b = append_check(p, "SSH/HTTPS Zugriff", id, split(value), [["WAN","wan"], ["Private","private"], ["Public","public"]]);
		addHelpText(b, "Zugang zur Konfiguration \xfcber verschiedene Anschl\xfcsse/Netzwerke erm\xf6glichen.")
		break;
	case "service_link":
		b = append_input(p, "Service Link", id, value);
		b.lastChild.placeholder = "http://[fdef:17a0::1]/seite.html";
		addInputCheck(b.lastChild,/^[#\[\] \w\/.:]{0,128}$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Verweis auf eine Netzwerkresource. Z.B. \"http://1.2.3.4\".");
		break;
	case "service_label":
		b = append_input(p, "Service Name", id, value);
		b.lastChild.placeholder = "MeineWebseite";
		addInputCheck(b.lastChild,/^[\[\]\(\) \w\/.:]{0,32}$/$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Name der angegebenen Netzwerkresource. Z.B. \"Meine Webseite\".");
		break;
	case "service_display_max":
		b = append_input(p, "Max. Angezeigte-Eintr\xe4ge", id, value);
		addInputCheck(b.lastChild,/^\d+$/, "Ung\xfcltige Zahl.");
		addHelpText(b, "Maximale Anzahl der auf der Statusseite angezeigten Eintr\xe4ge.");
		break;
	default:
		return;
	}

	b.id = id; //needed for updateFrom
	b.onchange = function() {
		updateFrom(b);
	};

	return b;
}

function rebuild_general()
{
	var gfs = $("general");
	var rfs = $("resource");
	var tfs = $("traffic");

	removeChilds(gfs);
	removeChilds(rfs);
	removeChilds(tfs);

	if('freifunk' in uci) {
		var f = uci.freifunk;
		var i = firstSectionID(f, "settings");
		appendSetting(gfs, ['freifunk', i, "name"], f[i]["name"]);
		appendSetting(gfs, ['freifunk', i, "geo"], f[i]["geo"]);
		appendSetting(gfs, ['freifunk', i, "map_publish"], f[i]["map_publish"]);
		appendSetting(gfs, ['freifunk', i, "access_from"], f[i]["access_from"]);
		appendSetting(rfs, ['freifunk', i, "service_label"], f[i]["service_label"]);
		appendSetting(rfs, ['freifunk', i, "service_link"], f[i]["service_link"]);
		appendSetting(rfs, ['freifunk', i, "service_display_max"], f[i]["service_display_max"]);
	}

	if('autoupdater' in uci) {
		var a = uci.autoupdater;
		var i = firstSectionID(a, "autoupdater");
		appendSetting(gfs, ['autoupdater', i, "enabled"], a[i]["enabled"]);
	}

	if('simple-tc' in uci) {
		var t = uci['simple-tc'];
		var i = firstSectionID(t, "interface");
		appendSetting(tfs, ['simple-tc', i, "enabled"], t[i]["enabled"]);
		appendSetting(tfs, ['simple-tc', i, "limit_ingress"], t[i]["limit_ingress"]);
		appendSetting(tfs, ['simple-tc', i, "limit_egress"], t[i]["limit_egress"]);
	}
}

function save_data()
{
	for(var name in uci)
	{
		var obj = uci[name];
		if(!obj.pchanged)
			continue;
		var data = toUCI(obj);
		send("/cgi-bin/misc", { func : "set_config_file", name : name, data : data },
			function(data) {
				$('msg').innerHTML = data;
				$('msg').focus();
				init();
			}
		);
	}
}
<commit_msg>add some minor white spaces<commit_after>
/*
All required uci packages are stored variable uci.
The GUI code displayes and manipulated this variable.
*/
var uci = {};
var gid = 0;

function init()
{
	send("/cgi-bin/settings", { func : "get_settings" }, function(data) {
		uci = fromUCI(data);
		rebuild_general();
	});
}

function updateFrom(src)
{
	var obj = {};
	collect_inputs(src, obj);
	for(var name in obj)
	{
		var value = obj[name];
		var path = name.split('#');

		var pkg = path[0];
		var sec = path[1];
		var opt = path[2];

		uci[pkg].pchanged = true;
		uci[pkg][sec][opt] = value
	}
}

function getChangeModeAction(ifname)
{
	return function(e) {
		var src = (e.target || e.srcElement);
		var mode = src.value;
		delNetSection(ifname);
		addNetSection(ifname, mode);
	};
}

function appendSetting(p, path, value, mode)
{
	var id = path.join('#');
	var b;
	var cfg = path[0]
	var name = path[path.length-1];
	switch(name)
	{
	case "geo":
		b = append_input(p, "GPS-Koordinaten", id, value);
		b.lastChild.placeholder = "52.02713078 8.52829987";
		addInputCheck(b.lastChild, /^\d{1,3}\.\d{1,8} +\d{1,3}\.\d{1,8}$/, "Koordinaten ist ung\xfcltig.");
		addHelpText(b, "Die Koordinaten dieses Knotens auf der Freifunk-Karte (z.B. \"52.02713078 8.52829987\").");
		break;
	case "name":
		b = append_input(p, "Knotenname", id, value);
		b.lastChild.placeholder = "MeinRouter";
		addInputCheck(b.lastChild, /^[\-\^'\w\.\:\[\]\(\)\/ \u0080-\u00FF]{0,32}$/, name + " ist ung\xfcltig.");
		addHelpText(b, "Der Name dieses Knotens auf der Freifunk-Karte.");
		break;
	case "enabled":
		if(cfg == "autoupdater") {
			b = append_radio(p, "Autoupdater", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Der Autoupdater aktualisiert die Firmware automatisch auf die neuste Version. Dabei werden allerdings alle Einstellungen zur\xfcckgesetzt.");
		}
		if(cfg == "simple-tc") {
			b = append_radio(p, "Bandweitenkontrolle", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Bandweitenkontrolle f\xfcr den Upload-/Download \xfcber das Freifunknetz \xfcber den eigenen Internetanschluss.");
		}
		break;
	case "map_publish":
		b = append_radio(p, "Zur Karte beitragen", id, value, [["Ja", "1"], ["Nein", "0"]]);
		addHelpText(b, "Soll dieser Knoten auf der Knotenkarte angezeigt werden?");
		break;
	case "limit_egress":
		b = append_input(p, "Public Upload", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Upload ist ung\xfcltig.");
		addHelpText(b, "Maximaler Upload in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "limit_ingress":
		b = append_input(p, "Public Download", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Download ist ung\xfcltig.");
		addHelpText(b, "Maximaler Download in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "access_from":
		b = append_check(p, "SSH/HTTPS Zugriff", id, split(value), [["WAN","wan"], ["Private","private"], ["Public","public"]]);
		addHelpText(b, "Zugang zur Konfiguration \xfcber verschiedene Anschl\xfcsse/Netzwerke erm\xf6glichen.")
		break;
	case "service_link":
		b = append_input(p, "Service Link", id, value);
		b.lastChild.placeholder = "http://[fdef:17a0::1]/seite.html";
		addInputCheck(b.lastChild, /^[#\[\] \w\/.:]{0,128}$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Verweis auf eine Netzwerkresource. Z.B. \"http://1.2.3.4\".");
		break;
	case "service_label":
		b = append_input(p, "Service Name", id, value);
		b.lastChild.placeholder = "MeineWebseite";
		addInputCheck(b.lastChild, /^[\[\]\(\) \w\/.:]{0,32}$/$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Name der angegebenen Netzwerkresource. Z.B. \"Meine Webseite\".");
		break;
	case "service_display_max":
		b = append_input(p, "Max. Angezeigte-Eintr\xe4ge", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Ung\xfcltige Zahl.");
		addHelpText(b, "Maximale Anzahl der auf der Statusseite angezeigten Eintr\xe4ge.");
		break;
	default:
		return;
	}

	b.id = id; //needed for updateFrom
	b.onchange = function() {
		updateFrom(b);
	};

	return b;
}

function rebuild_general()
{
	var gfs = $("general");
	var rfs = $("resource");
	var tfs = $("traffic");

	removeChilds(gfs);
	removeChilds(rfs);
	removeChilds(tfs);

	if('freifunk' in uci) {
		var f = uci.freifunk;
		var i = firstSectionID(f, "settings");
		appendSetting(gfs, ['freifunk', i, "name"], f[i]["name"]);
		appendSetting(gfs, ['freifunk', i, "geo"], f[i]["geo"]);
		appendSetting(gfs, ['freifunk', i, "map_publish"], f[i]["map_publish"]);
		appendSetting(gfs, ['freifunk', i, "access_from"], f[i]["access_from"]);
		appendSetting(rfs, ['freifunk', i, "service_label"], f[i]["service_label"]);
		appendSetting(rfs, ['freifunk', i, "service_link"], f[i]["service_link"]);
		appendSetting(rfs, ['freifunk', i, "service_display_max"], f[i]["service_display_max"]);
	}

	if('autoupdater' in uci) {
		var a = uci.autoupdater;
		var i = firstSectionID(a, "autoupdater");
		appendSetting(gfs, ['autoupdater', i, "enabled"], a[i]["enabled"]);
	}

	if('simple-tc' in uci) {
		var t = uci['simple-tc'];
		var i = firstSectionID(t, "interface");
		appendSetting(tfs, ['simple-tc', i, "enabled"], t[i]["enabled"]);
		appendSetting(tfs, ['simple-tc', i, "limit_ingress"], t[i]["limit_ingress"]);
		appendSetting(tfs, ['simple-tc', i, "limit_egress"], t[i]["limit_egress"]);
	}
}

function save_data()
{
	for(var name in uci)
	{
		var obj = uci[name];
		if(!obj.pchanged)
			continue;
		var data = toUCI(obj);
		send("/cgi-bin/misc", { func : "set_config_file", name : name, data : data },
			function(data) {
				$('msg').innerHTML = data;
				$('msg').focus();
				init();
			}
		);
	}
}
<|endoftext|>


<commit_before>  function _S4(){
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
  }

  function _guid(){
    return (_S4()+_S4()+"-"+_S4()+"-"+_S4()+"-"+_S4()+"-"+_S4()+_S4()+_S4());
  }

  function _indexPop(key) {
      localStorage.removeItem(key);
      k = key;
       var index = this._indexGet();
       var position = index.indexOf(key);
       if(position != -1){
      index = index.filter(function(val) {return val != key.toString()});
         }
         this._indexSet(index);
  }

   function _indexGet() {
       var index = this._storeGet('index');
       return index ? index : [];
     }

    function _indexAdd(key){
      var index = this._indexGet();
    index.push(key);
      this._indexSet(index);
    }

    function _indexSet(index) {
      localStorage.setItem('index', JSON.stringify(index));
    }

    function _getAll() {
      var r = [];
      var keys = this._indexGet();
      for (var i = 0 ; i < keys.length ; i++){
        var rv = this._storeGet(keys[i]);
        if (rv != undefined) r.push(rv);
      }
      return r
    }

    function _storeGet(key){
      try{
        return JSON.parse(localStorage.getItem(key));
      } catch(e){
        alert('ohhh my gosh! you tried to get and parse an invalid record! check your json.');
        return false
      }
    }

    function _storeSet(key,value){
      localStorage.setItem(key, JSON.stringify(value));
      this._indexAdd(key);
    }

  var List = Backbone.Collection.extend({
    model: Item
  });

  index = _indexGet();

  var ItemView = Backbone.View.extend({
    tagName: 'li',
    events: {
      'click span.delete': 'remove'
    },
    initialize: function(){
      _.bindAll(this, 'render', 'unrender', 'remove');
      this.model.bind('remove', this.unrender);
    },
    render: function(){
      $(this.el).html(''+this.model.get('Todo')+'[X][EDIT]');
      return this;
    },
    unrender: function(){
      $(this.el).remove();
    },
    remove: function(){
      var id = this.model.get('id_todo');
      _indexPop(id);
      this.model.destroy();
    },

  });

  var ListView = Backbone.View.extend({
    el: $('body'),
    events: {
      'keypress input#add': 'addItem'
    },
    initialize: function(){
      _.bindAll(this, 'render', 'addItem', 'appendItem');
      this.collection = new List();
      this.collection.bind('add', this.appendItem);
      this.render();
    },

    count: function(){
      this.collection.add(_getAll())
    },

    render: function(){
      $(this.el).append("<input id='add'></input>");
      $(this.el).append("

");
      _(this.collection.models).each(function(item){
        appendItem(item);
      }, this);
      this.count();
    },

    addItem: function(){
      if (event.keyCode == 13 && add.value!=''){
        var item = new Item();
        item.set({
          id_todo: _guid(),
          Todo: add.value
        });
        item.save();
        this.collection.add(item);
        add.value = '';
      }
    },

    appendItem: function(item){
      var itemView = new ItemView({
        model: item
      });
      $('ul', this.el).append(itemView.render().el);
    }
  });
<commit_msg>edit functions on views<commit_after>  function _S4(){
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
  }

  function _guid(){
    return (_S4()+_S4()+"-"+_S4()+"-"+_S4()+"-"+_S4()+"-"+_S4()+_S4()+_S4());
  }

  function _indexPop(key) {
      localStorage.removeItem(key);
      k = key;
       var index = this._indexGet();
       var position = index.indexOf(key);
       if(position != -1){
      index = index.filter(function(val) {return val != key.toString()});
         }
         this._indexSet(index);
  }

   function _indexGet() {
       var index = this._storeGet('index');
       return index ? index : [];
     }

    function _indexAdd(key){
      var index = this._indexGet();
    index.push(key);
      this._indexSet(index);
    }

    function _indexSet(index) {
      localStorage.setItem('index', JSON.stringify(index));
    }

    function _getAll() {
      var r = [];
      var keys = this._indexGet();
      for (var i = 0 ; i < keys.length ; i++){
        var rv = this._storeGet(keys[i]);
        if (rv != undefined) r.push(rv);
      }
      return r
    }

    function _storeGet(key){
      try{
        return JSON.parse(localStorage.getItem(key));
      } catch(e){
        alert('ohhh my gosh! you tried to get and parse an invalid record! check your json.');
        return false
      }
    }

    function _storeSet(key,value){
      localStorage.setItem(key, JSON.stringify(value));
      this._indexAdd(key);
    }

  var List = Backbone.Collection.extend({
    model: Item
  });

  index = _indexGet();

  var ItemView = Backbone.View.extend({
    tagName: 'li',
    events: {
      'click span.delete': 'remove',
      'click span.edit': 'edit',
      'keypress input#modify': 'modItem'
    },
    initialize: function(){
      _.bindAll(this, 'render', 'unrender', 'remove');
      this.model.bind('remove', this.unrender);
    },
    render: function(){
      $(this.el).html(''+this.model.get('Todo')+'[X][EDIT]');
      return this;
    },
    unrender: function(){
      $(this.el).remove();
    },
    remove: function(){
      var id = this.model.get('id_todo');
      _indexPop(id);
      this.model.destroy();
    },
    edit: function(){
      $(this.el).html("<input id='modify'></input>");
    },
    modItem: function(){
      if (event.keyCode == 13 && modify.value!=''){
        var val = modify.value;
        var id = this.model.get('id_todo');
        var item = new Item();
        item.set({
          id_todo: id,
          Todo: val
        });
        _indexPop(id);
        item.save();
      $(this.el).html(''+val+'[X][EDIT]');
      }
    }

  });

  var ListView = Backbone.View.extend({
    el: $('body'),
    events: {
      'keypress input#add': 'addItem'
    },
    initialize: function(){
      _.bindAll(this, 'render', 'addItem', 'appendItem');
      this.collection = new List();
      this.collection.bind('add', this.appendItem);
      this.render();
    },

    count: function(){
      this.collection.add(_getAll())
    },

    render: function(){
      $(this.el).append("<input id='add'></input>");
      $(this.el).append("

");
      _(this.collection.models).each(function(item){
        appendItem(item);
      }, this);
      this.count();
    },

    addItem: function(){
      if (event.keyCode == 13 && add.value!=''){
        var item = new Item();
        item.set({
          id_todo: _guid(),
          Todo: add.value
        });
        item.save();
        this.collection.add(item);
        add.value = '';
      }
    },

    appendItem: function(item){
      var itemView = new ItemView({
        model: item
      });
      $('ul', this.el).append(itemView.render().el);
    }
  });
<|endoftext|>


<commit_before>/**
 * Created by Kun on 7/5/2015.
 */

var itemDetailView = {
    productID: null,
    item: null,

    init: function () {
        $("#response").text("");
        this.productID = window.args.ProductID;

        var self = this;

        $.get(window.apiRoute + "/itemDetail/" + this.productID, function (response) {
            if (response && response.length) {
                self.item = jQuery.parseJSON(response)[0];
                //console.log(self.item);
                self.productName = self.item.Name;
                self.displayItem();
            } else {
                self.renderError("No inventory found");
            }
        }).fail(function (response) {
            self.renderError("Failed to load inventory: " + response);
        });
    },

    displayItem: function () {
        $("#response").text("");
        $("#product_name").text(this.item.Name);
        $("#details").append("
Total Available: " + this.item.TotalAvailable + "
" +
        "
Total Reserved: " + this.item.TotalReserved + "
" +
        "
Last run: " + this.item.MostRecent + "
");
    },

    renderError: function (error) {
        $("#response").text("Error: " + error);
    },

    add: function () {
        if (!this.productID || !this.item) return;
        navigation.go("AddInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    pull: function () {
        if (!this.productID || !this.item) return;
        navigation.go("PullInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            TotalQuantity: this.item.TotalAvailable,
            PreviousPage: "ItemDetailView.html"
        });
    },

    edit: function () {
        if (!this.productID || !this.item) return;
        navigation.go("EditProduct.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    Delete: function() {
        var productID = window.args.ProductID;
        $.get(window.apiRoute + "/DeleteProductByID/" + productID, function (resp) {
            var r = jQuery.parseJSON(resp);
            if (r[0].message == 'Success') {
                alert("Product " + $("#product_name").text() + " is deleted.");
                navigation.go("DisplayInventory.html",{ProductID: window.args.ProductID, PreviousPage:"ItemDetailView"});
            }
            else {
                alert(r[0].message);
                //$("#response").append("
" + "Deleting Product is only available to system admin.");
                //$("#response").append("
" + "Please go through the following checklist before deleting product.");
                //$("#response").append("
" + "1. Inventory of the product is 0.");
                //$("#response").append("
" + "2. De-associate all customers from the product");
            }
        }).fail(function (res) {
            $("#response").text( "Fail to delete product: Error --- " + res );
        });
    },

    back: function () {
        navigation.go("DisplayInventory.html", {ProductID: window.args.ProductID});
    }

};
<commit_msg>ItemDetailView Updated<commit_after>/**
 * Created by Kun on 7/5/2015.
 */

var itemDetailView = {
    productID: null,
    item: null,

    init: function () {
        $("#response").text("");
        this.productID = window.args.ProductID;

        var self = this;

        navigation.hit("/itemDetail/" + this.productID, function (response) {
            if (response && response.length) {
                self.item = jQuery.parseJSON(response)[0];
                //console.log(self.item);
                self.productName = self.item.Name;
                self.displayItem();
            } else {
                self.renderError("No inventory found");
            }
        })/*.fail(function (response) {
            self.renderError("Failed to load inventory: " + response);
        })*/;
    },

    displayItem: function () {
        $("#response").text("");
        $("#product_name").text(this.item.Name);
        $("#details").append("
Total Available: " + this.item.TotalAvailable + "
" +
        "
Total Reserved: " + this.item.TotalReserved + "
" +
        "
Last run: " + this.item.MostRecent + "
");
    },

    renderError: function (error) {
        $("#response").text("Error: " + error);
    },

    add: function () {
        if (!this.productID || !this.item) return;
        navigation.go("AddInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    pull: function () {
        if (!this.productID || !this.item) return;
        navigation.go("PullInventory.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            TotalQuantity: this.item.TotalAvailable,
            PreviousPage: "ItemDetailView.html"
        });
    },

    edit: function () {
        if (!this.productID || !this.item) return;
        navigation.go("EditProduct.html", {
            ProductID: this.productID,
            ProductName: this.item.Name || "",
            PreviousPage: "ItemDetailView.html"
        });
    },

    Delete: function() {
        var productID = window.args.ProductID;
        navigation.hit( "/DeleteProductByID/" + productID, function (resp) {
            var r = jQuery.parseJSON(resp);
            if (r[0].message == 'Success') {
                alert("Product " + $("#product_name").text() + " is deleted.");
                navigation.go("DisplayInventory.html",{ProductID: window.args.ProductID, PreviousPage:"ItemDetailView"});
            }
            else {
                alert(r[0].message);
                //$("#response").append("
" + "Deleting Product is only available to system admin.");
                //$("#response").append("
" + "Please go through the following checklist before deleting product.");
                //$("#response").append("
" + "1. Inventory of the product is 0.");
                //$("#response").append("
" + "2. De-associate all customers from the product");
            }
        })/*.fail(function (res) {
            $("#response").text( "Fail to delete product: Error --- " + res );
        })*/;
    },

    back: function () {
        navigation.go("DisplayInventory.html", {ProductID: window.args.ProductID});
    }

};
<|endoftext|>


<commit_before>var app = app || {};

$(function() {
        'use strict';

        // Organize Tab View
        // ---------------

	// The OrganizeView is the UI piece for the Organize tab in the App.
	app.OrganizeView = Backbone.View.extend({

		// Instead of generating a new element, bind to the existing skeleton
		// of the Organize tab already present in the HTML.
		el: '#organize',

		// TODO: Template for the sum row

                // Delegated events for creating and deleting debts
                events: {
			'click .form-cell':		'showFormInput',
                        'click #debt-add':		'createOnAdd',
			'keypress .debt-input':		'createOrUpdate',
			'blur .debt-input':		'hideFormInput'
                },

                // At initialization we bind to the relevant events in the 'Debts'
                // collection when debts are added or changed.
                initialize: function() {
			window.app.Debts.on( 'reset change remove', this.render, this );
			window.app.Debts.on( 'add reset', this.addAll, this );
			window.app.Debts.on( 'creation-error', this.formError, this );
			window.app.Debts.on( 'error', this.modelError, this );

                        this.title = this.$('#debt-title');
                        this.type = this.$('#debt-type');
                        this.principal = this.$('#debt-principal');
                        this.rate = this.$('#debt-rate');
                        this.repayment = this.$('#debt-repayment');

			this.$debtTable = this.$('#debt-table-wrapper');
			this.$principalTotal = this.$('#principal-total');
			this.$monthlyTotal = this.$('#monthly-total');

			// Wrap the debt inputs in a list for ease of processing.
			this.debtInputs = [this.title, this.type, this.principal, this.rate, this.repayment];

			// Enable the help pop-overs for each of the debt inputs.
			_.each( this.debtInputs, this.enablePopovers, this );

			// Kick things off by adding all debts to table
			this.addAll();
                },

                // Re-rendering the Organize view means showing or hiding the debt table
		// and redrawing the sum row.
                render: function( eventName ) {
			console.log( 'OrganizeView render() called with "' + eventName + '"' );

			// Pluck all the principal values from each model in the Debts collection
			// and reduce them down to a sum and update the html.
			var principalSum = _.reduce(window.app.Debts.pluck("principal"),
				function(sum, num) { return sum + num; }, 0 );
			this.$principalTotal.html( accounting.formatMoney(principalSum) );

			// Pluck all the monthly values from each model in the Debts collection
			// and reduce them down to a sum and update the html.
			var monthlySum = _.reduce(window.app.Debts.pluck("monthly"),
				function(sum, num) { return sum + num; }, 0 );
			this.$monthlyTotal.html( accounting.formatMoney(monthlySum) );

			if ( eventName == 'reset' || eventName == 'add' || eventName == 'destroy') {
				switch ( app.Debts.length ) {
					case 0:
						this.$debtTable.hide();
						break;
					case 1:
						this.$debtTable.show('blind', 700);
						break;
					default:
						this.$debtTable.show();
						break;
				}
			}
                },

		// On view close, we unbind all callbacks previously bound in initialize().
		onClose: function() {
			window.app.Debts.off( null, null, this );
		},

		// Helper function that iterates over the debtInputs and creates unique popovers.
		enablePopovers: function( input ) {
			var title = '';
			var content = '';

			switch ( input.attr('data-field') ) {
				case 'title':
					title = 'Debt Title';
					content = 'A descriptive title for this debt.';
					break;
				case 'type':
					title = 'Type';
					content = 'The debt type affects how monthly payments are calculated.';
					break;
				case 'principal':
					title = 'Starting Principal';
					content = 'The initial dollar amount of this debt.';
					break;
				case 'rate':
					title = 'Percentage Rate';
					content = 'The annual interest rate (percentage) of this debt.';
					break;
				case 'repayment':
					title = 'Repayment Time';
					content = 'The lifetime of this debt in months. Normally the default is 120 months (10 years).';
					break;
				default:
					break;
			}

			input.popover({
				placement: 'top',
				title: title,
				content: content,
				trigger: 'focus'
			});
		},

		// Uses the event's currentTarget's data-form attribute to find the input that
		// needs to be shown. Also sets a reference to the .view div that contains the text
		// for the current input.
		showFormInput: function( event ) {
			var formInput = event.currentTarget.getAttribute('data-form');
			this.currentInput = this.$('#' + formInput);

			var cell = $('td[data-form="' + formInput + '"]');
			this.currentInputView = cell.find('.view');
			this.displayFormInput( cell );
		},

		// Positions the current debt form input based on its parent cell, adds the
		// 'editing' and 'focused' classes and sets focus.
		displayFormInput: function( cell ) {
			this.currentInput.width( cell.find('.view').innerWidth() );
			this.currentInput.height( cell.find('.view').innerHeight() );
			cell.addClass('editing focused');
			this.currentInput.focus();
		},

		// Removes the editing (which hides the input) and focused classes from the table
		// cell containing the input. If the value is not empty, it updates the associated
		// view with the current input and adds the 'not-empty' class. If the value is empty,
		// it sets it back to its default, which is given by the 'data-default' attribute.
		hideFormInput: function() {
			this.currentInputView.parent().removeClass('editing focused');

			var value = this.currentInput.val();
			if ( value ) {
				this.currentInputView.html( this.currentInput.val() );
				this.currentInputView.parent().addClass('not-empty');
			} else {
				this.currentInputView.html( this.currentInput.attr('data-default') );
				this.currentInputView.parent().removeClass('not-empty');
			}
		},

		// Add a single debt to the list by creating a view for it and
		// appending its element to the table
		addOne: function( debt ) {
			var view = new app.DebtView({ model: debt});
			$('#debt-table-body').append( view.render('OrganizeView:addOne').el );
		},

		// Add all debts in the **Debts** collection at once.
		// Remove all debt-view rows from the table and current errors.
		addAll: function() {
			this.$('.debt-view').remove();
			this.clearErrors();
			app.Debts.each( this.addOne, this );
		},

		// Generate the attributes for a new Debt item.
		// First sanitize the strings from the input fields
		// and convert to proper types before sending off to the model.
		newAttributes: function() {
			return {
				title: this.title.val().trim(),
				type: this.type.val().trim(),
				principal: app.toFixed( parseFloat(this.principal.val().trim().replace('/,/g', '')) ),
				rate: app.toFixed( parseFloat(this.rate.val().trim()) ),
				repayment: parseInt( this.repayment.val().trim() ),
				order: app.Debts.nextOrder()
			};
		},

		// If you click on the Add button, create new **Debt** model,
		// persisting it to *LocalStorage*.
		createOnAdd: function( e ) {
			// Clear any current errors
			this.clearErrors();

			// Create new model in collection, check if successful
			if ( app.Debts.create( this.newAttributes() ) ) {
				this.clearFormInputs();
			}
		},

		// If the enter key is pressed while in a debt input, attempt to create a new debt.
		// If the tab key is pressed, find the next tabindex to focus on.
		createOrUpdate: function( e ) {
				if ( e.which == ENTER_KEY ) {
					this.createOnAdd();
				} else if ( e.which == TAB_KEY ) {
					console.log('TODO: switch to the next tabindex input');
				}
		},

		// Helper function that clears debt form input fields and resets form cell views.
		clearFormInputs: function() {
				this.title.val('');
				this.type.val(DEBT_TYPES[0]);
				this.principal.val('');
				this.rate.val('');
				this.repayment.val('');
				$('.form-cell').each(function(idx, item) {
					var defaultText = $(this).find('[data-default]').attr('data-default');
					$(this).find('.view').html(defaultText);
					$(this).removeClass('not-empty');
				});
		},

		// Debt from error handling.
		// Add the 'error' class to all appropriate control-groups in the form
		// then flash the error messages.
		// The trigger for function comes from event manually fired from the Debt Model
		// during validation to take care of returning errors during model creation.
		formError: function( model, errors ) {
			_.each( errors, function(error){
				$('#' + error.field + '-group').addClass('error'); });

			app.AlertHandler.trigger( 'app:alert', errors, 'error' );
		},

		// Debt model error handling.
		// Trigger for this function comes from the 'error' event that is
		// automatically fired when the model fails validation.
		// In this case we do not want to highlight the form inputs so
		// we clear them out (since during model validation failure both
		// automatic 'error' and manual 'creation-error' are fired.).
		modelError: function( model, errors ) {
			this.clearErrors();

			// Since this will only be fired from model if validation fails
			// after a model already is created, go ahead and re-render the
			// debt creation form since we just cleared any errors it might have had.
			this.clearFormInputs();

			app.AlertHandler.trigger( 'app:alert', errors, 'error' );
		},

		clearErrors: function() {
			$('.control-group').removeClass('error');
			$('.alert').alert('close');
		}
	});
});
<commit_msg>Implemented error styling of debt creation form cell views.<commit_after>var app = app || {};

$(function() {
        'use strict';

        // Organize Tab View
        // ---------------

	// The OrganizeView is the UI piece for the Organize tab in the App.
	app.OrganizeView = Backbone.View.extend({

		// Instead of generating a new element, bind to the existing skeleton
		// of the Organize tab already present in the HTML.
		el: '#organize',

		// TODO: Template for the sum row

                // Delegated events for creating and deleting debts
                events: {
			'click .form-cell':		'showFormInput',
                        'click #debt-add':		'createOnAdd',
			'keypress .debt-input':		'createOrUpdate',
			'blur .debt-input':		'hideFormInput'
                },

                // At initialization we bind to the relevant events in the 'Debts'
                // collection when debts are added or changed.
                initialize: function() {
			window.app.Debts.on( 'reset change remove', this.render, this );
			window.app.Debts.on( 'add reset', this.addAll, this );
			window.app.Debts.on( 'creation-error', this.formError, this );
			window.app.Debts.on( 'error', this.modelError, this );

                        this.title = this.$('#debt-title');
                        this.type = this.$('#debt-type');
                        this.principal = this.$('#debt-principal');
                        this.rate = this.$('#debt-rate');
                        this.repayment = this.$('#debt-repayment');

			this.$debtTable = this.$('#debt-table-wrapper');
			this.$principalTotal = this.$('#principal-total');
			this.$monthlyTotal = this.$('#monthly-total');

			// Wrap the debt inputs in a list for ease of processing.
			this.debtInputs = [this.title, this.type, this.principal, this.rate, this.repayment];

			// Enable the help pop-overs for each of the debt inputs.
			_.each( this.debtInputs, this.enablePopovers, this );

			// Kick things off by adding all debts to table
			this.addAll();
                },

                // Re-rendering the Organize view means showing or hiding the debt table
		// and redrawing the sum row.
                render: function( eventName ) {
			console.log( 'OrganizeView render() called with "' + eventName + '"' );

			// Pluck all the principal values from each model in the Debts collection
			// and reduce them down to a sum and update the html.
			var principalSum = _.reduce(window.app.Debts.pluck("principal"),
				function(sum, num) { return sum + num; }, 0 );
			this.$principalTotal.html( accounting.formatMoney(principalSum) );

			// Pluck all the monthly values from each model in the Debts collection
			// and reduce them down to a sum and update the html.
			var monthlySum = _.reduce(window.app.Debts.pluck("monthly"),
				function(sum, num) { return sum + num; }, 0 );
			this.$monthlyTotal.html( accounting.formatMoney(monthlySum) );

			if ( eventName == 'reset' || eventName == 'add' || eventName == 'destroy') {
				switch ( app.Debts.length ) {
					case 0:
						this.$debtTable.hide();
						break;
					case 1:
						this.$debtTable.show('blind', 700);
						break;
					default:
						this.$debtTable.show();
						break;
				}
			}
                },

		// On view close, we unbind all callbacks previously bound in initialize().
		onClose: function() {
			window.app.Debts.off( null, null, this );
		},

		// Helper function that iterates over the debtInputs and creates unique popovers.
		enablePopovers: function( input ) {
			var title = '';
			var content = '';

			switch ( input.attr('data-field') ) {
				case 'title':
					title = 'Debt Title';
					content = 'A descriptive title for this debt.';
					break;
				case 'type':
					title = 'Type';
					content = 'The debt type affects how monthly payments are calculated.';
					break;
				case 'principal':
					title = 'Starting Principal';
					content = 'The initial dollar amount of this debt.';
					break;
				case 'rate':
					title = 'Percentage Rate';
					content = 'The annual interest rate (percentage) of this debt.';
					break;
				case 'repayment':
					title = 'Repayment Time';
					content = 'The lifetime of this debt in months. Normally the default is 120 months (10 years).';
					break;
				default:
					break;
			}

			input.popover({
				placement: 'top',
				title: title,
				content: content,
				trigger: 'focus'
			});
		},

		// Uses the event's currentTarget's data-form attribute to find the input that
		// needs to be shown. Also sets a reference to the .view div that contains the text
		// for the current input.
		showFormInput: function( event ) {
			var formInput = event.currentTarget.getAttribute('data-form');
			this.currentInput = this.$('#' + formInput);

			var cell = $('td[data-form="' + formInput + '"]');
			this.currentInputView = cell.find('.view');
			this.displayFormInput( cell );
		},

		// Positions the current debt form input based on its parent cell, adds the
		// 'editing' and 'focused' classes and sets focus.
		displayFormInput: function( cell ) {
			this.currentInput.width( cell.find('.view').innerWidth() );
			this.currentInput.height( cell.find('.view').innerHeight() );
			cell.addClass('editing focused');
			this.currentInput.focus();
		},

		// Removes the editing (which hides the input) and focused classes from the table
		// cell containing the input. If the value is not empty, it updates the associated
		// view with the current input and adds the 'not-empty' class. If the value is empty,
		// it sets it back to its default, which is given by the 'data-default' attribute.
		hideFormInput: function() {
			this.currentInputView.parent().removeClass('editing focused');

			var value = this.currentInput.val();
			if ( value ) {
				this.currentInputView.html( this.currentInput.val() );
				this.currentInputView.parent().addClass('not-empty');
			} else {
				this.currentInputView.html( this.currentInput.attr('data-default') );
				this.currentInputView.parent().removeClass('not-empty');
			}
		},

		// Add a single debt to the list by creating a view for it and
		// appending its element to the table
		addOne: function( debt ) {
			var view = new app.DebtView({ model: debt});
			$('#debt-table-body').append( view.render('OrganizeView:addOne').el );
		},

		// Add all debts in the **Debts** collection at once.
		// Remove all debt-view rows from the table and current errors.
		addAll: function() {
			this.$('.debt-view').remove();
			this.clearErrors();
			app.Debts.each( this.addOne, this );
		},

		// Generate the attributes for a new Debt item.
		// First sanitize the strings from the input fields
		// and convert to proper types before sending off to the model.
		newAttributes: function() {
			return {
				title: this.title.val().trim(),
				type: this.type.val().trim(),
				principal: app.toFixed( parseFloat(this.principal.val().trim().replace('/,/g', '')) ),
				rate: app.toFixed( parseFloat(this.rate.val().trim()) ),
				repayment: parseInt( this.repayment.val().trim() ),
				order: app.Debts.nextOrder()
			};
		},

		// If you click on the Add button, create new **Debt** model,
		// persisting it to *LocalStorage*.
		createOnAdd: function( e ) {
			// Clear any current errors
			this.clearErrors();

			// Create new model in collection, check if successful
			if ( app.Debts.create( this.newAttributes() ) ) {
				this.clearFormInputs();
			}
		},

		// If the enter key is pressed while in a debt input, attempt to create a new debt.
		// If the tab key is pressed, find the next tabindex to focus on.
		createOrUpdate: function( e ) {
				if ( e.which == ENTER_KEY ) {
					this.createOnAdd();
				} else if ( e.which == TAB_KEY ) {
					console.log('TODO: switch to the next tabindex input');
				}
		},

		// Helper function that clears debt form input fields and resets form cell views.
		clearFormInputs: function() {
				this.title.val('');
				this.type.val(DEBT_TYPES[0]);
				this.principal.val('');
				this.rate.val('');
				this.repayment.val('');
				$('.form-cell').each(function(idx, item) {
					var defaultText = $(this).find('[data-default]').attr('data-default');
					$(this).find('.view').html(defaultText);
					$(this).removeClass('not-empty');
				});
		},

		// Debt from error handling.
		// Add the 'error' class to all appropriate control-groups in the form
		// then flash the error messages.
		// The trigger for function comes from event manually fired from the Debt Model
		// during validation to take care of returning errors during model creation.
		formError: function( model, errors ) {
			_.each( errors, function(error){
				$('[data-form="debt-' + error.field + '"]').addClass('error');
			});

			app.AlertHandler.trigger( 'app:alert', errors, 'error' );
		},

		// Debt model error handling.
		// Trigger for this function comes from the 'error' event that is
		// automatically fired when the model fails validation.
		// In this case we do not want to highlight the form inputs so
		// we clear them out (since during model validation failure both
		// automatic 'error' and manual 'creation-error' are fired.).
		modelError: function( model, errors ) {
			this.clearErrors();

			// Since this will only be fired from model if validation fails
			// after a model already is created, go ahead and re-render the
			// debt creation form since we just cleared any errors it might have had.
			this.clearFormInputs();

			app.AlertHandler.trigger( 'app:alert', errors, 'error' );
		},

		clearErrors: function() {
			$('.form-cell').removeClass('error');
			$('.alert').alert('close');
		}
	});
});
<|endoftext|>


<commit_before>'use strict';

angular.module('eMarketApp').directive('shoppingCart', function(User, Helper) {
  return {
    templateUrl: 'views/shoppingCart.html',
    restrict: 'E',
    scope: {},
    replace: true,
    controller: function($scope, Product, CartInfo) {

      $scope.setItem = function(cartProduct) {
        var copy = angular.copy(cartProduct);
        copy.id = copy.productId;
        Product.setItem(copy);
      };

      $scope.setCostAndShipping = function(items, cost, shipping) {
        CartInfo.setCartInfo(items, cost, shipping);
      };

    },
    link: function(scope, elem) {

      var page = $(elem[0]);

      var shoppingCartList = page.find('#cart-shoppingCartList');
      var proceedToCheckOut = page.find('#cart-proceedToCheckoutBtn');
      var deleteCartItemBtn = page.find('#cart-deleteItemCartBtn');

      var statusPopup = page.find('#cart-statusPopup');
      var statusPopupMessage = page.find('#cart-statusPopupMessage');
      var shoppingCartPopup = page.find('#cart-notificationPopup');

      var cartSelected = null;
      var selectedCartIndex = null;

      scope.cost = 0;
      scope.shipping = 0;

      var computeTotalCostAndShipping = function() {
        scope.cost = 0;
        scope.shipping = 0;
        window._.each(scope.shoppingCarts, function(cart) {
          if(cart.isBidItem) {
            scope.cost += cart.productTotalBidPrice;
          } else {
            scope.cost += cart.productTotalNonBidPrice;
          }
          scope.shipping += cart.shippingPrice;
        });
      };

      scope.selectCart = function(cartItem, index) {
        cartSelected = cartItem;
        selectedCartIndex = index;

        if(scope.shoppingCarts[selectedCartIndex].isBidItem) { // Check if it is a bid item
          deleteCartItemBtn.addClass('ui-disabled');
        } else {
          deleteCartItemBtn.removeClass('ui-disabled');
        }
      };

      scope.deleteCartItem = function() {
        shoppingCartPopup.off();
        statusPopup.off();
        $.mobile.loading('show');

        User.me().one('cartItems', scope.shoppingCarts[selectedCartIndex].itemId).remove().then(function() {
          scope.shoppingCarts.splice(selectedCartIndex, 1);
          computeTotalCostAndShipping();
          if(scope.shoppingCarts.length === 0) {
            proceedToCheckOut.addClass('ui-disabled');
          }
          Helper.refreshList(shoppingCartList);

          $.mobile.loading('hide');
          shoppingCartPopup.on({
            popupafterclose: function() {
              statusPopupMessage.text('Product Deleted Successfully From Cart.');
              setTimeout(function() {
                statusPopup.popup('open');
                shoppingCartPopup.off();
              });
            }
          });
        }, function(err) {
          $.mobile.loading('hide');
          shoppingCartPopup.on({
            popupafterclose: function() {
              statusPopupMessage.text('Product Not Deleted Successfully From Cart.');
              setTimeout(function() {
                statusPopup.popup('open');
                shoppingCartPopup.off();
              });
            }
          });
          console.log('Error Removing Product From Cart', err);
        });
      };

      page.on('pagebeforeshow', function() {

        User.me().getList('cartItems').then(function(carts) {
          scope.shoppingCarts = carts;
          Helper.refreshList(shoppingCartList);
          computeTotalCostAndShipping();
          if(scope.shoppingCarts.length === 0) {
            proceedToCheckOut.addClass('ui-disabled');
          } else {
            proceedToCheckOut.removeClass('ui-disabled');
          }
        }, function(err) {
          scope.shoppingCarts = [];
          Helper.refreshList(shoppingCartList);
          console.log('Empty Cart', err);
        });
      });

      page.on('pageshow', function() {

        statusPopup.off();
        if(scope.shoppingCarts.length === 0) {
          statusPopupMessage.text('No items in cart, please buy some :)');
          statusPopup.popup('open');
        }
      });
    }
  };
});
<commit_msg>Refresh the total price in cart if there is no item in there<commit_after>'use strict';

angular.module('eMarketApp').directive('shoppingCart', function(User, Helper) {
  return {
    templateUrl: 'views/shoppingCart.html',
    restrict: 'E',
    scope: {},
    replace: true,
    controller: function($scope, Product, CartInfo) {

      $scope.setItem = function(cartProduct) {
        var copy = angular.copy(cartProduct);
        copy.id = copy.productId;
        Product.setItem(copy);
      };

      $scope.setCostAndShipping = function(items, cost, shipping) {
        CartInfo.setCartInfo(items, cost, shipping);
      };

    },
    link: function(scope, elem) {

      var page = $(elem[0]);

      var shoppingCartList = page.find('#cart-shoppingCartList');
      var proceedToCheckOut = page.find('#cart-proceedToCheckoutBtn');
      var deleteCartItemBtn = page.find('#cart-deleteItemCartBtn');

      var statusPopup = page.find('#cart-statusPopup');
      var statusPopupMessage = page.find('#cart-statusPopupMessage');
      var shoppingCartPopup = page.find('#cart-notificationPopup');

      var cartSelected = null;
      var selectedCartIndex = null;

      scope.cost = 0;
      scope.shipping = 0;

      var computeTotalCostAndShipping = function() {
        scope.cost = 0;
        scope.shipping = 0;
        window._.each(scope.shoppingCarts, function(cart) {
          if(cart.isBidItem) {
            scope.cost += cart.productTotalBidPrice;
          } else {
            scope.cost += cart.productTotalNonBidPrice;
          }
          scope.shipping += cart.shippingPrice;
        });
      };

      scope.selectCart = function(cartItem, index) {
        cartSelected = cartItem;
        selectedCartIndex = index;

        if(scope.shoppingCarts[selectedCartIndex].isBidItem) { // Check if it is a bid item
          deleteCartItemBtn.addClass('ui-disabled');
        } else {
          deleteCartItemBtn.removeClass('ui-disabled');
        }
      };

      scope.deleteCartItem = function() {
        shoppingCartPopup.off();
        statusPopup.off();
        $.mobile.loading('show');

        User.me().one('cartItems', scope.shoppingCarts[selectedCartIndex].itemId).remove().then(function() {
          scope.shoppingCarts.splice(selectedCartIndex, 1);
          computeTotalCostAndShipping();
          if(scope.shoppingCarts.length === 0) {
            proceedToCheckOut.addClass('ui-disabled');
          }
          Helper.refreshList(shoppingCartList);

          $.mobile.loading('hide');
          shoppingCartPopup.on({
            popupafterclose: function() {
              statusPopupMessage.text('Product Deleted Successfully From Cart.');
              setTimeout(function() {
                statusPopup.popup('open');
                shoppingCartPopup.off();
              });
            }
          });
        }, function(err) {
          $.mobile.loading('hide');
          shoppingCartPopup.on({
            popupafterclose: function() {
              statusPopupMessage.text('Product Not Deleted Successfully From Cart.');
              setTimeout(function() {
                statusPopup.popup('open');
                shoppingCartPopup.off();
              });
            }
          });
          console.log('Error Removing Product From Cart', err);
        });
      };

      page.on('pagebeforeshow', function() {

        User.me().getList('cartItems').then(function(carts) {
          scope.shoppingCarts = carts;
          Helper.refreshList(shoppingCartList);
          computeTotalCostAndShipping();
          if(scope.shoppingCarts.length === 0) {
            proceedToCheckOut.addClass('ui-disabled');
          } else {
            proceedToCheckOut.removeClass('ui-disabled');
          }
        }, function(err) {
          scope.shoppingCarts = [];
          computeTotalCostAndShipping();
          Helper.refreshList(shoppingCartList);
          console.log('Empty Cart', err);
        });
      });

      page.on('pageshow', function() {

        statusPopup.off();
        if(scope.shoppingCarts.length === 0) {
          statusPopupMessage.text('No items in cart, please buy some :)');
          statusPopup.popup('open');
        }
      });
    }
  };
});
<|endoftext|>


<commit_before>//abstract base class
function InboxStateObject(elem) {
    this.baseUrl = $("input[name='baseUrl']").val();
    this.elem = elem;
    this.currentUrl = window.location.pathname;
    this.message = "Feedback is broadcasted and moved to " + "Published Folder";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}

InboxStateObject.prototype.undo = function() {

    var me = this;
    $(document).delegate("a.undo", "click", function(e) {
        var undo_type = $(this).attr('undo-type');
        var undo_mode = $('.inbox-state').val();

        var current_catid = me.elem.attr('catid');
        var state_data = {"mode": undo_mode, "feed_ids": [me.feeds], "cat_id": current_catid, "href": me.href}
        var sec = 350;

        $("#" + me.feeds.feedid).fadeIn(sec);
        $(this).parents("."+undo_type).fadeOut(sec, function() { $(this).remove(); });

        console.log(me.feeds);

        console.log(state_data);
        change_state(state_data);
        e.preventDefault();
    });
}

InboxStateObject.prototype.process = function() {

    var me = this;
    var is_single = $(me).attr('feedid');
    var mode = (me.state == 1) ? "inbox" : me.mode;
    var state_data = { "mode": mode, "feed_ids": [me.feeds], "cat_id": me.catid, "href": me.href }
    var state_view_data;

    //console.log(state_data);
    if(is_single) {
        if(me.currentUrl.match(/published|contacts/g)) {
            //HTML view transforms
            if(mode == 'feature') {
                state_view_data = {
                    'elem': me.elem
                  , 'color': '#FFFFE0'
                  , 'position': '-60px -34px'
                  , 'sibling': '.check'
                };
                checky_bar_message(me, true);
                change_view(state_view_data);
            }

            if(mode == 'publish') {
                state_view_data = {
                    'elem': me.elem
                  , 'color': '#FFFFFF'
                  , 'position': '0px -34px'
                  , 'sibling': '.feature'
                };
                checky_bar_message(me, true);
                change_view(state_view_data);
            }

            //these modes will fadeout feeds in the publish and contact modules
            if(mode == 'inbox' || mode == 'delete') {
                $(me.elem).parents('.feedback').fadeOut(350);
                if(mode == 'inbox') {
                    me.message = "feedback returned to inbox";
                }
                checky_bar_message(me);
            }
            change_state(state_data);
        } else {
            $(me.elem).parents('.feedback').fadeOut(350);
            checky_bar_message(me);
            change_state(state_data);
        }
    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })

}

//child implementation classes
function PublishStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been published.";
    this.mode    = "publish";
}
PublishStateObject.prototype = new InboxStateObject();

function FeatureStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been featured.";
    this.mode    = "feature";
}
FeatureStateObject.prototype = new InboxStateObject();

function RemoveStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been " + "deleted";
    this.mode    = "delete";
}
RemoveStateObject.prototype = new InboxStateObject();

function CatPickObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been sent to " + "Filed Feedback";
    this.mode    = "fileas";
    $(elem).parents('div.category-picker-holder').hide();
}

CatPickObject.prototype = new InboxStateObject();
CatPickObject.prototype.process = function() {

    var me = this;
    var is_single = $(me).attr('feedid');
    var mode = me.mode;
    var state_data = { "mode": mode, "feed_ids": [me.feeds], "cat_id": me.catid, "href": me.href }
    //console.log(state_data);
    if(is_single) {
        if(me.currentUrl.match(/filed|modifyfeedback/g)) {
            change_state(state_data);
        } else {
            $(me.elem).parents('.feedback').fadeOut(350);
            checky_bar_message(me);
            change_state(state_data);
        }
    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })
}

//Factory
function InboxStatusChange(opts)  {
    this.inbox_controls = opts;
}

InboxStatusChange.prototype.initialize = function() {
    var me = this;
    $(document).delegate(me.inbox_controls, 'click', function(e) {
        var identifier = $(this).attr('class');
        var us = $(this);

        $.ajax({url: "/feedback/bust_hostfeed_data"});

        if(identifier == 'check') {
            var check = new PublishStateObject(us);
            check.process();
            check.undo();
        }

        if(identifier == 'feature') {
            var feature = new FeatureStateObject(us);
            feature.process();
            feature.undo();
        }

        if(identifier == 'remove' || identifier == 'popup-delete') {
            var remove = new RemoveStateObject(us);
            remove.process();
            remove.undo();
        }
    })
}

function checky_bar_message(opts, undo_msg) {

    var undo_msg = typeof undo_msg !== 'undefined' ? undo_msg : false;

    var check_message = $('.checky-bar');
    var undo = "  Undo";
    var close_checky = "  Close";

    var notify_msg = opts.message + undo + close_checky;

    if(undo_msg) {
        var notify_msg = opts.message;
    }

    var notify  = $('
').addClass(opts.identifier).css({'text-align': 'center'}).html(notify_msg);

    check_message.html(notify).show();
}

function change_view(opts) {
    $(opts.elem).parents('.feedback').css({'background-color': opts.color});
    $(opts.elem).css({'background-position': opts.position});
    $(opts.elem).attr('state', 1);
    $(opts.elem).siblings(opts.sibling).removeAttr('style');
    $(opts.elem).siblings(opts.sibling).attr('state', 0);
}

function change_state(state_data) {
    $.ajax({
        type: "POST"
      , url: state_data.href
      , data: state_data
      , success: function() {
            var myStatus = new Status();
            myStatus.notify("Processing...", 1000);
        }
    });
}
<commit_msg>kiciking<commit_after>//abstract base class
function InboxStateObject(elem) {
    this.baseUrl = $("input[name='baseUrl']").val();
    this.elem = elem;
    this.currentUrl = window.location.pathname;
    this.message = "Feedback is broadcasted and moved to " + "Published Folder";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}

InboxStateObject.prototype.undo = function() {

    var me = this;
    $(document).delegate("a.undo", "click", function(e) {
        var undo_type = $(this).attr('undo-type');
        var undo_mode = $('.inbox-state').val();

        var current_catid = me.elem.attr('catid');
        var state_data = {"mode": undo_mode, "feed_ids": [me.feeds], "cat_id": current_catid, "href": me.href}
        var sec = 350;

        $("#" + me.feeds.feedid).fadeIn(sec);
        $(this).parents("."+undo_type).fadeOut(sec, function() { $(this).remove(); });

        console.log(state_data);
        change_state(state_data);
        e.preventDefault();
    });
}

InboxStateObject.prototype.process = function() {

    var me = this;
    var is_single = $(me).attr('feedid');
    var mode = (me.state == 1) ? "inbox" : me.mode;
    var state_data = { "mode": mode, "feed_ids": [me.feeds], "cat_id": me.catid, "href": me.href }
    var state_view_data;

    //console.log(state_data);
    if(is_single) {
        if(me.currentUrl.match(/published|contacts/g)) {
            //HTML view transforms
            if(mode == 'feature') {
                state_view_data = {
                    'elem': me.elem
                  , 'color': '#FFFFE0'
                  , 'position': '-60px -34px'
                  , 'sibling': '.check'
                };
                checky_bar_message(me, true);
                change_view(state_view_data);
            }

            if(mode == 'publish') {
                state_view_data = {
                    'elem': me.elem
                  , 'color': '#FFFFFF'
                  , 'position': '0px -34px'
                  , 'sibling': '.feature'
                };
                checky_bar_message(me, true);
                change_view(state_view_data);
            }

            //these modes will fadeout feeds in the publish and contact modules
            if(mode == 'inbox' || mode == 'delete') {
                $(me.elem).parents('.feedback').fadeOut(350);
                if(mode == 'inbox') {
                    me.message = "feedback returned to inbox";
                }
                checky_bar_message(me);
            }
            change_state(state_data);
        } else {
            $(me.elem).parents('.feedback').fadeOut(350);
            checky_bar_message(me);
            change_state(state_data);
        }
    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })

}

//child implementation classes
function PublishStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been published.";
    this.mode    = "publish";
}
PublishStateObject.prototype = new InboxStateObject();

function FeatureStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been featured.";
    this.mode    = "feature";
}
FeatureStateObject.prototype = new InboxStateObject();

function RemoveStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been " + "deleted";
    this.mode    = "delete";
}
RemoveStateObject.prototype = new InboxStateObject();

function CatPickObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.message = "Feedback has been sent to " + "Filed Feedback";
    this.mode    = "fileas";
    $(elem).parents('div.category-picker-holder').hide();
}

CatPickObject.prototype = new InboxStateObject();
CatPickObject.prototype.process = function() {

    var me = this;
    var is_single = $(me).attr('feedid');
    var mode = me.mode;
    var state_data = { "mode": mode, "feed_ids": [me.feeds], "cat_id": me.catid, "href": me.href }
    //console.log(state_data);
    if(is_single) {
        if(me.currentUrl.match(/filed|modifyfeedback/g)) {
            change_state(state_data);
        } else {
            $(me.elem).parents('.feedback').fadeOut(350);
            checky_bar_message(me);
            change_state(state_data);
        }
    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })
}

//Factory
function InboxStatusChange(opts)  {
    this.inbox_controls = opts;
}

InboxStatusChange.prototype.initialize = function() {
    var me = this;
    $(document).delegate(me.inbox_controls, 'click', function(e) {
        var identifier = $(this).attr('class');
        var us = $(this);

        $.ajax({url: "/feedback/bust_hostfeed_data"});

        if(identifier == 'check') {
            var check = new PublishStateObject(us);
            check.process();
            check.undo();
        }

        if(identifier == 'feature') {
            var feature = new FeatureStateObject(us);
            feature.process();
            feature.undo();
        }

        if(identifier == 'remove' || identifier == 'popup-delete') {
            var remove = new RemoveStateObject(us);
            remove.process();
            remove.undo();
        }
    })
}

function checky_bar_message(opts, undo_msg) {

    var undo_msg = typeof undo_msg !== 'undefined' ? undo_msg : false;

    var check_message = $('.checky-bar');
    var undo = "  Undo";
    var close_checky = "  Close";

    var notify_msg = opts.message + undo + close_checky;

    if(undo_msg) {
        var notify_msg = opts.message;
    }

    var notify  = $('
').addClass(opts.identifier).css({'text-align': 'center'}).html(notify_msg);

    check_message.html(notify).show();
}

function change_view(opts) {
    $(opts.elem).parents('.feedback').css({'background-color': opts.color});
    $(opts.elem).css({'background-position': opts.position});
    $(opts.elem).attr('state', 1);
    $(opts.elem).siblings(opts.sibling).removeAttr('style');
    $(opts.elem).siblings(opts.sibling).attr('state', 0);
}

function change_state(state_data) {
    $.ajax({
        type: "POST"
      , url: state_data.href
      , data: state_data
      , success: function() {
            var myStatus = new Status();
            myStatus.notify("Processing...", 1000);
        }
    });
}
<|endoftext|>