 
         if not require('./feature').IS_MOBILE
             @frame.$("#site").css("padding-left", "20px")
+
+        if not @read_only
+            $(@iframe[0].contentWindow.document).keydown (evt) =>
+                if evt.ctrlKey or evt.metaKey or evt.altKey
+                    if evt.keyCode == 83 # s
+                        @emit('save')
+                        evt.preventDefault()
+                        evt.stopPropagation()
+                        return false
+
 
     monkey_patch_logo: () =>
         @frame.$("#ipython_notebook").find("a").click () =>


    show: (width) =>
        @iframe?.attr('width', width).maxheight()
        setTimeout((()=>@iframe?.maxheight()), 1)   # set it one time more the next render loop.

    line_to_cell: (line) =>
        obj = JSON.parse(line)

                if @dom.read_only
                    # DOM gets extra info about @read_only status of file from jupyter notebook server.
                    @read_only = true
                else
                    # not read only, so make "command/control+s" save.
                    #@dom.frame.keydown (e) =>
                    #    console.log("frame keydown ", e)
                cb()
        @dom = new JupyterWrapper(@notebook, @server_url, @filename, @read_only, @project_id, done)

    init_buttons: () =>
        # info button
        @element.find("a[href=#info]").click(@info)

        # time travel/history
        @element.find("a[href=#history]").click(@show_history_viewer)

        # save button
        if @read_only
            @element.find("a[href=#save]").addClass('disabled')
        else
            @save_button = @element.find("a[href=#save]").click(@save)

        # publish button
        @publish_button = @element.find("a[href=#publish]").click(@publish_ui)

    init_dom_events: () =>
