Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/apps/system/js/window.js
blob: a9109ddd929909d5361d303ef08081652dc495ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

(function(window){

  var _ = navigator.mozL10n.get;

  var ENABLE_LOG = false;

  // Use mutation observer to monitor appWindow status change
  window.AppLog = function AppLog(app) {
    // select the target node
    var target = app.frame;

    // create an observer instance
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        console.log(mutation.target.id,
                    mutation.target.className,
                    mutation.attributeName);
      });
    });

    // configuration of the observer:
    var config = { attributes: true };

    // pass in the target node, as well as the observer options
    observer.observe(target, config);
  }

  window.AppError = function AppError(app) {
    var self = this;
    this.app = app;
    this.app.frame.addEventListener('mozbrowsererror', function (evt) {
      if (evt.detail.type != 'other')
        return;

      console.warn('app of [' + self.app.origin + '] got a mozbrowsererror event.');

      if (self.injected) {
        self.update();
      } else {
        self.render();
      }
      self.show();
      self.injected = true;
    });
    return this;
  };

  AppError.className = 'appError';

  AppError.prototype.hide = function() {
    this.element.classList.remove('visible');
  }

  AppError.prototype.show = function() {
    this.element.classList.add('visible');
  }

  AppError.prototype.render = function() {
    this.app.frame.insertAdjacentHTML('beforeend', this.view());
    this.closeButton = this.app.frame.querySelector('.' + AppError.className + ' .close');
    this.reloadButton = this.app.frame.querySelector('.' + AppError.className + ' .reload');
    this.titleElement = this.app.frame.querySelector('.' + AppError.className + ' .title');
    this.messageElement = this.app.frame.querySelector('.' + AppError.className + ' .message');
    this.element = this.app.frame.querySelector('.' + AppError.className);
    var self = this;
    this.closeButton.onclick = function() {
      self.app.kill();
    }

    this.reloadButton.onclick = function() {
      self.hide();
      self.app.reload();
    }
  }

  AppError.prototype.update = function() {
    this.titleElement.textContent = this.getTitle();
    this.messageElement.textContent = this.getMessage();
  }

  AppError.prototype.id = function() {
    return AppError.className + '-' + this.app.frame.id;
  }

  AppError.prototype.getTitle = function() {
    if (AirplaneMode.enabled) {
      return _('airplane-is-on');
    } else if (!navigator.onLine) {
      return _('network-connection-unavailable');
    } else {
      return _('error-title', { name: this.app.name });
    }
  }

  AppError.prototype.getMessage = function() {
    if (AirplaneMode.enabled) {
      return _('airplane-is-turned-on', { name: this.app.name });
    } else if (!navigator.onLine) {
      return _('network-error', { name: this.app.name });
    } else {
      return _('error-message', { name: this.app.name });
    }
  }

  AppError.prototype.view = function() {
    return '<div id="' + this.id() + '" class="' + AppError.className + ' visible" role="dialog">' +
      '<div class="modal-dialog-message-container inner">' +
        '<h3 data-l10n-id="error-title" class="title">' + this.getTitle() + '</h3>' +
        '<p>' +
         '<span data-l10n-id="error-message" class="message">' + this.getMessage() + '</span>' +
        '</p>' +
      '</div>' +
      '<menu data-items="2">' +
        '<button class="close" data-l10n-id="try-again">' + _('close') + '</button>' +
        '<button class="reload" data-l10n-id="try-again">' + _('try-again') + '</button>' +
      '</menu>' +
    '</div>';
  }

  window.AppWindow = function AppWindow(configuration) {
    for (var key in configuration) {
      this[key] = configuration[key];
    }

    // We keep the appError object here for the purpose that
    // we may need to export the error state of AppWindow instance to the other module
    // in the future.
    this.appError = new AppError(this);
    if (ENABLE_LOG)
      this.appLog = new AppLog(this);

    return this;
  };

  AppWindow.prototype.reload = function() {
    this.iframe.reload(true);
  }

  AppWindow.prototype.kill = function() {
    // XXX: A workaround because a AppWindow instance shouldn't reference Window Manager directly here.
    // In the future we should make every app maintain and execute the events in itself.
    // Like resize, setVisibility...
    // And Window Manager is in charge of cross app management.
    WindowManager.kill(this.origin);
  }

}(this));