       iframe = $("iframe.plunker-previewer-iframe", $el)[0]
       childWindow = null
       
+      $scope.previewUrl ||= "#{url.run}/#{genid()}/" # Create a random new preview id
+      $scope.iframeUrl = "about:blank" # Initial url until a windowed -> embedded switch
       $scope.session = session
-      $scope.windowed = false
-      $scope.preview = new Preview
-        delegate: -> files: session.toJSON().files
-        handler: (data) ->
-          if $scope.windowed
-            if !childWindow or childWindow?.closed
-              childWindow = window.open data.run_url, "plnk_previewer", "resizable=yes,scrollbars=yes,status=yes,toolbar=yes"
-            else
-              childWindow.location.reload(true) # Fails on recent Chrome... try anyway ;-)
+      $scope.mode = "disabled"
+      
+      $scope.expand = -> $scope.mode = "windowed"
+      $scope.contract = -> $scope.mode = "embedded"
+      
+      $scope.refresh = -> $timeout ->
+        return if $scope.mode is "disabled"
+        
+        form = angular.element("""<form style="display: none;" method="post" action="#{$scope.previewUrl}" target="plunkerPreviewTarget"><form>""")
+        
+        for filename, file of session.toJSON().files
+          field = angular.element("""<input type="hidden" name="files[#{filename}][content]">""")
+          field.attr "value", file.content
+          
+          form.append(field)
+        
+        #$document.append(form)
+        
+        form.submit()
+        
+        $timeout -> form.remove()
+      
+      $scope.$watch "mode", (mode, old_mode) ->
+        switch mode
+          when "embedded"
+            childWindow?.close()
+            childWindow = null
+          
+            $timeout -> $scope.refresh() # Refresh on next tick to make sure DOM udpated first
+          when "windowed"
+            childWindow = window.open "about:blank", "plunkerPreviewTarget", "resizable=yes,scrollbars=yes,status=yes,toolbar=yes"
+            $timeout -> $scope.refresh() # Refresh on next tick to make sure DOM udpated first
             
-          else
-            loc = iframe.contentWindow.location
-            
-            if loc is data.run_url then loc.reload(true)
-            else loc.replace(data.run_url)
-      
-      $scope.refresh = -> $scope.preview.refresh()
-      $scope.expand = -> $scope.windowed = true
-      $scope.contract = -> $scope.windowed = false
-            
-      $scope.$watch "windowed", (windowed) ->
-        if windowed
-          pane.class = "windowed"
-          iframe.contentWindow.location.replace("about:blank")
-        else
-          pane.class = ""
-          childWindow?.close()
-          childWindow = null
-        $scope.preview.refresh() if pane.active
       
       $scope.$watch "pane.active", (active) ->
-        if active then $scope.preview.refresh()
-        else iframe.contentWindow.location.replace("about:blank")
+        if !active and $scope.mode is "embedded" then $scope.mode = "disabled"
+        if active and $scope.mode is "disabled" then $timeout ->
+          $scope.mode = "embedded"
         
       $scope.$watch "session.updated_at", ->
-        $scope.preview.refresh() if settings.previewer.auto_refresh and (pane.active or $scope.windowed)
+        $scope.refresh() if settings.previewer.auto_refresh and (pane.active or $scope.mode is "windowed")
       
       setInterval ->
-        if $scope.windowed and childWindow?.closed
+        if $scope.mode is "windowed" and childWindow?.closed
           $scope.$apply ->
-            $scope.windowed = false
+            $scope.contract()
             childWindow = null
       , 1000
 ]
module.service "previewer", ["$http", "$timeout", "url", "settings", "notifier", ($http, $timeout, url, settings, notifier) ->
]

module.run [ "$q", "$http", "$timeout", "url", "panes", "session", "settings", "notifier", ($q, $http, $timeout, url, panes, session, settings, notifier) ->

  class Preview
    constructor: (options = {}) ->
      @delegate = options.delegate or -> files: {'index.html': {content: ""}}
      @previewId = options.previewId or ""
      @handler = options.handler or ->
    
    refresh: (force = false) ->
      preview = @
      
      $timeout.cancel(@cancelCurrentRefresh) if @cancelCurrentRefresh
      
      @cancelCurrentRefresh = $timeout ->
        json = if angular.isFunction(preview.delegate) then preview.delegate() else preview.delegate
        req = $http.post("#{url.run}/#{preview.previewId}", json, cache: false).then (res) ->
          if res.status >= 400 then notifier.error("Preview refresh failed")
          else
            preview.previewId = res.data.id
            preview.handler(res.data)
            
        , (err) -> notifier.error("Preview refresh failed")
      , if force then 0 else settings.previewer.delay
      
  panes.add
    id: "preview"

    """
    size: "50%"
    template: """
      <div class="plunker-previewer" ng-switch on="mode">
        <div ng-switch-when="embedded">
          <div class="plunker-previewer-ops">
            <div class="btn-toolbar">
              <div class="btn-group">
                <button id="refresh-preview" ng-click="refresh()" class="btn btn-mini btn-success" title="Manually trigger a refresh of the preview"><i class="icon-refresh icon-white"></i></button>
                <button id="expand-preview" ng-click="expand()" class="btn btn-mini btn-primary" title="Launch the preview in a separate window"><i class="icon-fullscreen icon-white"></i></button>
              </div>
            </div>
          </div>
          <iframe name="plunkerPreviewTarget" src="{{iframeUrl}}" class="plunker-previewer-iframe" frameborder="0" width="100%" height="100%" scrolling="auto"></iframe>
        </div>
        <div ng-switch-when="windowed">
          <div class="well">
            <h4>Previeweing in windowed mode</h4>
            <p>You've switched to previewing your work in windowed mode. This can be useful for using the developer tools without having to navigate
              down through the iframe that is used for the in-window preview.</p>
            <p>You can return to the in-window preview at any time simply by clicking below.</p>
            <p>
              <button class="btn btn-success" ng-click="refresh()">
                <i class="icon-refresh"></i>
                Refresh
              </button>
              <button class="btn btn-danger" ng-click="contract()">
                <i class="icon-remove"></i>
                Close
              </button>
            </p>
          </div>
        </div>
      </div>
