示例#1
0
文件: simple.py 项目: jdunck/Tickery
    def __init__(self, topPanel):
        TickeryTab.__init__(self, topPanel)
        # Get query names (if they exist) from the request. We don't check
        # that we're the wanted tab: if 2 names are given, just use them.
        args = Window.getLocation().getSearchDict()
        name1 = args.get("name1")
        name2 = args.get("name2")

        if name1 and name2:
            self.autoActivate = True

        if name1:
            name1 = urllib.unquote_plus(name1)
        else:
            name1 = _defaultName1

        if name2:
            name2 = urllib.unquote_plus(name2)
        else:
            name2 = _defaultName2

        v1 = VerticalPanel()
        self.name1 = text.TextBoxFocusHighlight(
            Text=name1, MaxLength=self.textBoxLength, VisibleLength=self.textBoxLength, StyleName="simple-query-box"
        )
        v1.add(self.name1)
        self.followResult1 = HorizontalPanel(Spacing=4)
        v1.add(self.followResult1)

        v2 = VerticalPanel()
        self.name2 = text.TextBoxFocusHighlight(
            Text=name2, MaxLength=self.textBoxLength, VisibleLength=self.textBoxLength, StyleName="simple-query-box"
        )
        v2.add(self.name2)
        self.followResult2 = HorizontalPanel(Spacing=4)
        v2.add(self.followResult2)

        self.goButton = go.GoButton(self)

        v = VerticalPanel(Spacing=2, StyleName="help-panel")
        v.add(HTML("Enter two Twitter usernames", StyleName="simple-instructions"))
        v.add(v1)
        h = HorizontalPanel()
        h.add(v2)
        h.add(self.goButton)
        v.add(h)

        self.topGrid.setWidget(0, 1, v)
        formatter = self.topGrid.getCellFormatter()
        formatter.setHorizontalAlignment(0, 1, "left")

        self.checkResult = HorizontalPanel()
        self.add(self.checkResult)

        self.results = userlist.UserListPanel(self, topPanel)
        self.add(self.results)

        # allow keypress ENTER reaction
        self.name1.addKeyboardListener(self)
        self.name2.addKeyboardListener(self)
示例#2
0
 def replaceLinks(self, tagname="a"):
     """ replaces <tag href="#pagename">sometext</tag> with:
         Hyperlink("sometext", "pagename")
     """
     tags = self.findTags(tagname)
     pageloc = Window.getLocation()
     pagehref = pageloc.getPageHref()
     for el in tags:
         href = el.href
         l = href.split("#")
         if len(l) != 2:
             continue
         if l[0] != pagehref:
             continue
         token = l[1]
         if not token:
             continue
         html = DOM.getInnerHTML(el)
         parent = DOM.getParent(el)
         index = DOM.getChildIndex(parent, el)
         hl = Hyperlink(TargetHistoryToken=token,
                        HTML=html,
                        Element=DOM.createSpan())
         DOM.insertChild(parent, hl.getElement(), index)
         self.children.insert(index, hl)
         parent.removeChild(el)
示例#3
0
	def onModuleLoad(self):
		#Setup JSON RPC
                self.app_info = {}
		self.remote = DataService()

                # parse get data
		self.location = Window.getLocation().getHref()
		self.locLabel = Label(str(self.location))
		self.getData = self.location.split('?')
		self.getData = self.getData[len(self.getData)-1].split('&') #now an array of get data
		self.table_width = 800
		
		self.query = self.getData[1].split('=')[1]
		self.cat = self.getData[0].split('=')[1]

		#s = self.remote.testT()
		self.mainPanel = VerticalPanel()
		self.html_title = HTML("<h1>Search Results for books with %s containing \"%s\"</h1>" % (self.cat, self.query))
		self.SellList = FlexTable()
		
		#self.mainPanel.add(self.SellList)
		self.mainPanel.add(self.html_title)
		#self.mainPanel.add(self.locLabel)
		self.results = []
		self.remote.get_search_results(self,self.cat, self.query)
		RootPanel("results").add(self.mainPanel)
示例#4
0
    def replaceLinks(self, tagname="a", use_page_href=True, ajaxify=False):
        """ replaces <tag href="#pagename">sometext</tag> with:
            Hyperlink("sometext", "pagename").  Hyperlinks use
            the History module so the notification will come
            in on an onHistoryChanged.
        """
        self._clear_hyperlinks()
        tags = self.findTags(tagname)
        pageloc = Window.getLocation()
        pagehref = pageloc.getPageHref()
        for el in tags:
            href = el.href
            l = href.split("#")
            if len(l) != 2:
                continue
            if use_page_href and not l[0].startswith(pagehref):
                continue
            token = l[1]
            if not token:
                continue
            html = DOM.getInnerHTML(el)
            parent = DOM.getParent(el)
            index = DOM.getChildIndex(parent, el)
            if ajaxify:
                token = '!%s' % token
            hl = Hyperlink(TargetHistoryToken=token,
                           HTML=html,
                           Element=DOM.createSpan())
            DOM.insertChild(parent, hl.getElement(), index)
            parent.removeChild(el)

            self.children.insert(index, hl)
            hl.setParent(self)
            self.hyperlinks.append(hl)
示例#5
0
    def onModuleLoad(self):

        img_url = Window.getLocation().getSearchVar("img")
        if not img_url:
            img_url = 'images/chrome_clock.png'
        self.solar = SolarCanvas(img_url)
        
        RootPanel().add(self.solar)
        self.onShow()
示例#6
0
    def onModuleLoad(self):

        img_url = Window.getLocation().getSearchVar("img")
        if not img_url:
            img_url = 'images/chrome_clock.png'
        self.solar = SolarCanvas(img_url)

        RootPanel().add(self.solar)
        self.onShow()
示例#7
0
 def onTimer(self):
     print "hello"
     loc = Window.getLocation()
     print loc.getHash()
     print loc.getHost()
     print loc.getPageHref()
     print loc.getPathname()
     print loc.getSearchDict()
     Window.resize(300.0, 200.0)
示例#8
0
def AppInit():

    img_url = Window.getLocation().getSearchVar("img")
    if not img_url:
        img_url = 'images/chrome_clock.png'
    solar = SolarCanvas(img_url)
    
    solar.isActive = True
    solar.onTimer()

    return solar
示例#9
0
def AppInit():

    img_url = Window.getLocation().getSearchVar("img")
    if not img_url:
        img_url = 'images/chrome_clock.png'
    solar = SolarCanvas(img_url)

    solar.isActive = True
    solar.onTimer()

    return solar
示例#10
0
 def onSave(self):
     """
     Handle the save click and pass it onto the listeners.
     """
     log.debug("onSave() in %s", Window.getLocation().getHref())
     for listener in self.saveListeners:
         if hasattr(listener, "onSave"):
             listener.onSave(self)
         else:
             listener(self)
     return False
示例#11
0
 def onSave(self):
     """
     Handle the save click and pass it onto the listeners.
     """
     log.writebr("onSave() in %s", Window.getLocation().getHref())
     for listener in self.saveListeners:
         if hasattr(listener, "onSave"):
             listener.onSave(self)
         else:
             listener(self)
     return False
示例#12
0
文件: tabs.py 项目: jdunck/Tickery
 def setDefaultTab(self):
     args = Window.getLocation().getSearchDict()
     wantedTab = args.get('tab', self.simple.tabName).lower()
         
     if wantedTab == self.intermediate.tabName:
         self.selectTab(1)
     elif wantedTab == self.advanced.tabName:
         self.selectTab(2)
     elif wantedTab == self.about.tabName:
         self.selectTab(3)
     else:
         self.selectTab(0)
示例#13
0
文件: index.py 项目: jdunck/Tickery
    def __init__(self):
        SimplePanel.__init__(self, StyleName='main-panel')
        self.setWidth('100%')
        self.tabs = tabs.Tabs()
        self.tabs.addTabListener(self)
        self.add(self.tabs)
        
        Window.addWindowResizeListener(self)
        DeferredCommand.add(self)

        args = Window.getLocation().getSearchDict()
        userlist.setSortKey(args.get('sort'))        
        userlist.setIconSize(args.get('icons'))        
示例#14
0
    def __init__(self, topPanel):
        TickeryTab.__init__(self, topPanel)
        # Get the query string and wanted tab, if any, from URL args.
        args = Window.getLocation().getSearchDict()
        query = args.get('query')
        wantedTab = args.get('tab')
        if wantedTab:
            wantedTab = wantedTab.lower()
        if query and wantedTab == self.tabName.lower():
            query = urllib.unquote_plus(query)
            self.autoActivate = True
        else:
            query = self.defaultQuery
            
        self.instructions.setHorizontalAlignment(HasAlignment.ALIGN_LEFT)
        self.instructions.setStyleName('instructions-popup')
        self.popup = InstructionBox(
            self.__class__.__name__, self.instructions)
        self.popup.setText(self.instructionsTitle)
        self.db = Button(HELP_TEXT, StyleName='help-button')
        self.db.addClickListener(self)

        huhId = HTMLPanel.createUniqueId()
        help = HTMLPanel('%s <span id="%s"></span>' %
                             (SHORT_INSTRUCTIONS[self.tabName], huhId),
                             StyleName='simple-instructions')
        help.add(self.db, huhId)
        
        self.goButton = go.GoButton(self)
        self.query = text.TextAreaFocusHighlight(Text=query,
                                                 VisibleLines=3,
                                                 StyleName='large-query-area')
        self.checkResult = HorizontalPanel(Spacing=4)
        
        mainGrid = Grid(2, 2, StyleName='tickery-tab-panel',
                        HorizontalAlignment=HasAlignment.ALIGN_LEFT)
        formatter = mainGrid.getCellFormatter()
        mainGrid.setWidget(0, 0, help)
        mainGrid.setWidget(1, 0, self.query)
        mainGrid.setWidget(1, 1, self.goButton)
        formatter.setHorizontalAlignment(0, 0, 'left')
        formatter.setHorizontalAlignment(1, 0, 'left')
        formatter.setAlignment(1, 1, 'left', 'bottom')
        self.topGrid.setWidget(0, 1, mainGrid)
        
        self.add(self.checkResult)
        self.results = userlist.UserListPanel(self, topPanel,
            HorizontalAlignment=HasAlignment.ALIGN_LEFT)
        self.add(self.results)
示例#15
0
    def __init_UI(self):
        ## Two-phase to mimic flex_ui class
        Window.addWindowCloseListener(self)

        self.ws_dh = WSdataHandler(self, self.callback)
        location = Window.getLocation()
        search = location.getSearch()[1:]
        params = '/'.join(search.split('&'))
        full_resource = self.resource + '/' + params
        self.ws = websocketclient.WebSocketClient(full_resource, self.ws_dh,
                                                  fallback=bool(self.fallback))
        self.ws.connect(self.server)

        self.php_dh = PHPdataHandler(self, self.callback)
        self.php_script = self.resource + '.php'
        if not isinstance(self.fallback, bool):
            self.php_script = self.fallback
示例#16
0
    def __init__(self):
        url = Window.getLocation().getHref()

        variables = self.parse_url(url)

        if "assignmentId" not in variables.keys() or variables["assignmentId"] == "ASSIGNMENT_ID_NOT_AVAILABLE":
            self.accepted = False
        else:
            self.accepted = True

        # adds class variables if the hit is accepted

        if self.accepted == True:
            self.assignmentId = variables["assignmentId"]
            self.workerId = variables["workerId"]
            self.hitId = variables["hitId"]

        def is_standard_param(param):
            standard_params = ["assignmentId", "hitId", "workerId", "turkSubmitTo"]
            return param in standard_params

        self.params = dict((k, variables[k]) for k in variables.keys() if not is_standard_param(k))
示例#17
0
 def testLocation(self):
     self.assertTrue(
         Window.getLocation().getHref().endswith('LibTest.html'))
示例#18
0
 def testLocation(self):
     self.assertTrue(Window.getLocation().getHref().endswith(
         'LibTest.html'))
示例#19
0
 def onModuleLoad(self):
     section = Window.getLocation().getSearchVar("section")
     if not section:
         self.loadChapters()
     else:
         loadSection(section)
示例#20
0
文件: main.py 项目: antialize/djudge
 def onClose(self,env):
     Window.getLocation().setHref("http://www.google.com")
示例#21
0
文件: Bookreader.py 项目: Afey/pyjs
 def onModuleLoad(self):
     section = Window.getLocation().getSearchVar("section")
     if not section:
         self.loadChapters()
     else:
         loadSection(section)
示例#22
0
import pyjd # this is dummy in pyjs.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.Hyperlink import Hyperlink
from pyjamas.ui.Button import Button
from pyjamas.ui.HTML import HTML
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.Grid import Grid
from pyjamas.ui.Label import Label
from pyjamas.HTTPRequest import HTTPRequest
from pyjamas import Window
import pygwt
location = Window.getLocation()


def locationObjPanel():
	vpl = VerticalPanel();
	vpl.add(HTML(location.getPageHref(self)))
	vpl.add(HTML(location.getSearchVar('theme')))
	vpl.add(HTML(location.getSearch(self)))
	return vpl

# async request
class HTTPAsyncRequestHandler:
	"""
		Usage: 
			- 	Instantiation
			-	Subclassing:
			In both cases setting (texts, messagePanels), and/or (callbacks) parameter(s)
			in construction or through attributs
	"""
示例#23
0
	def get():
		return Window.getLocation()	
示例#24
0
    def __init__(self, left = 50, top = 50, fileLocation = None):
        global has_getAsText
        try:
            DialogBox.__init__(self, modal = False)
            self.filename = None
            self.data = None

            self.setPopupPosition(left, top)
            self.dockPanel = DockPanel()
            self.dockPanel.setSpacing(4)
            self.setText("File Open")

            if not fileLocation is None:
                msg = HTML("Loading file...", True)
                self.dockPanel.add(msg, DockPanel.NORTH)
                location =  fileLocation
                if fileLocation.find("://") < 0:
                    base = Window.getLocation().getHref()
                    if base.find('/') >= 0:
                        sep = '/'
                    else:
                        sep = '\\'
                    base = sep.join(base.split(sep)[:-1]) + sep
                    location = base + fileLocation
                self.iframe = Frame(location)
                self.dockPanel.add(self.iframe, DockPanel.CENTER)
            else:
                msg = HTML("Choose a file", True)

                self.browseFile = FileUpload()
                elem = self.browseFile.getElement()
                if False and has_getAsText and hasattr(elem, 'files'):
                    self.iframe = None
                    self.files = elem.files
                    self.dockPanel.add(self.browseFile, DockPanel.CENTER)
                else:
                    self.browseFile = None
                    self.files = None
                    base = '' + doc().location
                    if base.find('/') >= 0:
                        sep = '/'
                    else:
                        sep = '\\'
                    if not base.lower()[:5] == "file:":
                        base = "file:///C:/"
                        msg = HTML("You'll have to place the application on a local file system, otherwise the browser forbids access.", True)
                    else:
                        base = sep.join(base.split(sep)[:-1]) + sep
                    self.iframe = Frame(base)
                    self.dockPanel.add(self.iframe, DockPanel.CENTER)
                self.dockPanel.add(msg, DockPanel.NORTH)

            if self.iframe:
                self.iframe.setWidth("36em")
            hpanel = HorizontalPanel()
            self.openBtn = Button("Open", self.onClickOpen)
            hpanel.add(self.openBtn)
            self.cancelBtn = Button("Cancel", self.onClickCancel)
            hpanel.add(self.cancelBtn)
            self.dockPanel.add(hpanel, DockPanel.SOUTH)

            self.setWidget(self.dockPanel)
        except:
            raise
示例#25
0
文件: main.py 项目: antialize/djudge
 def logout(self, _):
     global gw
     gw.logout(self.cookie)
     self.cookie = None
     setCookie('cookie','',24*60*60)
     Window.getLocation().reload()
示例#26
0
    def __init__(self, left=50, top=50, fileLocation=None):
        global has_getAsText
        try:
            DialogBox.__init__(self, modal=False)
            self.filename = None
            self.data = None

            self.setPopupPosition(left, top)
            self.dockPanel = DockPanel()
            self.dockPanel.setSpacing(4)
            self.setText("File Open")

            if not fileLocation is None:
                msg = HTML("Loading file...", True)
                self.dockPanel.add(msg, DockPanel.NORTH)
                location = fileLocation
                if fileLocation.find("://") < 0:
                    base = Window.getLocation().getHref()
                    if base.find('/') >= 0:
                        sep = '/'
                    else:
                        sep = '\\'
                    base = sep.join(base.split(sep)[:-1]) + sep
                    location = base + fileLocation
                self.iframe = Frame(location)
                self.dockPanel.add(self.iframe, DockPanel.CENTER)
            else:
                msg = HTML("Choose a file", True)

                self.browseFile = FileUpload()
                elem = self.browseFile.getElement()
                if False and has_getAsText and hasattr(elem, 'files'):
                    self.iframe = None
                    self.files = elem.files
                    self.dockPanel.add(self.browseFile, DockPanel.CENTER)
                else:
                    self.browseFile = None
                    self.files = None
                    base = '' + doc().location
                    if base.find('/') >= 0:
                        sep = '/'
                    else:
                        sep = '\\'
                    if not base.lower()[:5] == "file:":
                        base = "file:///C:/"
                        msg = HTML(
                            "You'll have to place the application on a local file system, otherwise the browser forbids access.",
                            True)
                    else:
                        base = sep.join(base.split(sep)[:-1]) + sep
                    self.iframe = Frame(base)
                    self.dockPanel.add(self.iframe, DockPanel.CENTER)
                self.dockPanel.add(msg, DockPanel.NORTH)

            if self.iframe:
                self.iframe.setWidth("36em")
            hpanel = HorizontalPanel()
            self.openBtn = Button("Open", self.onClickOpen)
            hpanel.add(self.openBtn)
            self.cancelBtn = Button("Cancel", self.onClickCancel)
            hpanel.add(self.cancelBtn)
            self.dockPanel.add(hpanel, DockPanel.SOUTH)

            self.setWidget(self.dockPanel)
        except:
            raise
示例#27
0
    def onModuleLoad(self):
        self.remote = DataService()

        # do JSON RPC calls
        self.remote.get_facebook_user(self)
        self.remote.get_app_info(self, "verify")

        # labels and banners
        self.html_verify_banner = HTML("<h1>Verify your NetID</h1>")
        self.html_confirm_banner = HTML("<h1>Confirming your NetID...</h1>")

        self.lbl_verify_text = Label("Please verify your account.")
        self.lbl_confirm_text = Label("Confirming Acount...")
        self.lbl_confirm_result = Label()

        # textboxes
        self.tb_verify_netid = TextBox()

        # hook up keyboard events
        send_confirmation_email = self.send_confirmation_email
        class Add_KeyboardHandler():
            def onKeyPress(self, sender, keycode, modifiers):
                if keycode == KEY_ENTER:
                    send_confirmation_email()
            def onKeyDown(self, sender, keycode, modifiers): return
            def onKeyUp(self, sender, keycode, modifiers): return
        self.kbh = Add_KeyboardHandler()
        self.tb_verify_netid.addKeyboardListener(self.kbh)

        # buttons
        self.btn_verify = Button("Verify!", self.send_confirmation_email)

        # NetID information form
        self.table_verify_netid = FlexTable()
        self.table_verify_netid.setText(0, 0, "NetID:")
        self.table_verify_netid.setWidget(0, 1, self.tb_verify_netid)
        self.table_verify_netid.setWidget(1, 1, self.btn_verify)

        # panels
        self.main_panel = VerticalPanel()

        # check get information, if present, verify, if not request form
        self.location = Window.getLocation().getHref()
        self.tmp = self.location.split('?')
        self.tmp = self.tmp[len(self.tmp) - 1].split("&")
        for e in self.tmp:
            get_var = e.split("=")
            if len(get_var) == 2:
                PageVerify.get_data[get_var[0]] = get_var[1]

        if "vk" in PageVerify.get_data:
            # we have request from verification email
            self.main_panel.add(self.html_confirm_banner)
            self.main_panel.add(self.lbl_confirm_text)
            self.main_panel.add(self.lbl_confirm_result)
            self.verify_user()
        else:
            self.main_panel.add(self.html_verify_banner)
            self.main_panel.add(self.lbl_verify_text)
            self.main_panel.add(self.table_verify_netid)
            
        self.main_panel.addStyleName("verify_panel")

        # add everything to root panel
        RootPanel("page_verify").add(self.main_panel)
示例#28
0
import pyjd # this is dummy in pyjs.
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.HTML import HTML
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas import Window
from editor import Editor
from viewer import Viewer

if __name__ == '__main__':
    pyjd.setup("public/cbrow.html")

    full_url = Window.getLocation().getHref()
    db_url = '/'.join(full_url.split('/')[:4])+'/'
    editor_panel = VerticalPanel()
    editor = Editor(db_url, editor_panel)
    viewer = Viewer(db_url, RootPanel(), editor.loadDocument)
    sep = HTML('<hr style="height:10" />')
    editor.onModuleLoad()
    viewer.onModuleLoad()
    RootPanel().add(sep)
    RootPanel().add(editor_panel)
    viewer.setView('_all_docs')

    pyjd.run()
示例#29
0
    def onModuleLoad(self):
        # parse get data
        self.location = Window.getLocation().getHref()
        self.get_data = {}
        self.tmp = self.location.split('?')
        self.tmp = self.tmp[len(self.tmp) - 1].split("&")
        for e in self.tmp:
            get_var = e.split("=")
            if len(get_var) == 2:
                self.get_data[get_var[0]] = get_var[1]

        # JSON RPC response holders
        self.facebook_user = {}
        self.app_info = {}
        self.sellers = []
        self.book = {}
        self.has_book = "none"
        
        # setup JSON RPC
        self.remote = DataService()

        self.remote.get_facebook_user(self)
        self.remote.get_app_info(self, "book_detail")
        if "asin" in self.get_data:
            self.remote.get_book_details(self, self.get_data["asin"])
            self.remote.get_sellers(self, self.get_data["asin"])
            self.remote.user_has_book(self, self.get_data["asin"])

        # create panels
        self.main_panel = HorizontalPanel()
        self.info_panel = VerticalPanel()
        self.sell_btn_panel = VerticalPanel()
        self.wish_btn_panel = VerticalPanel()
        self.seller_panel = VerticalPanel()
        self.add_comment_panel = VerticalPanel()

        # images
        self.img_book_cover = Image()

        # html labels
        self.html_book_title = HTML()
        self.html_book_author = HTML()
        self.html_book_isbn10 = HTML()
        self.html_book_publisher = HTML()
        self.html_book_publish_date = HTML()
        self.html_book_edition = HTML()
        self.html_book_binding = HTML()

        self.html_btn_sell = HTML()
        self.html_btn_wish = HTML()
        
        self.html_seller_title = HTML()

        # check for no get data!
        if "asin" not in self.get_data:
            self.html_book_title.setHTML("<h1>Book not found!</h1>\n<p>The book you are looking for does not exist.</p>")
            self.info_panel.setWidth("100%")
            self.main_panel.setWidth("100%")
            self.info_panel.add(self.html_book_title)
            self.main_panel.add(self.info_panel)
            RootPanel("page_book_comments").add(self.main_panel)
            return

        # add to sellers panel
        self.seller_panel.add(self.html_seller_title)
        self.seller_panel.addStyleName("comments")

        self.info_panel.add(self.html_book_title)
        self.info_panel.add(self.html_book_author)
        self.info_panel.add(self.html_book_isbn10)
        self.info_panel.add(self.html_book_publisher)
        self.info_panel.add(self.html_book_publish_date)
        self.info_panel.add(self.html_book_edition)
        self.info_panel.add(self.html_book_binding)
        self.info_panel.add(self.add_comment_panel)
        self.info_panel.add(self.seller_panel)
        self.info_panel.addStyleName("info_panel")
        
        self.main_panel.add(self.info_panel)
        self.main_panel.add(self.img_book_cover)
        
        RootPanel("page_book_comments").add(self.main_panel)
        
        # spin until book info get here
        class SpinTimer(Timer):
            def __init__(self, max_tries = 10, interval = 500):
                Timer.__init__(self)
                self.interval = interval
                self.max_tries = max_tries
                self.tries = 0
                self.func = func
                self.params = params
                self.scheduleRepeating(self.interval)

            def run(self):
                self.tries += 1

                if self.tries >= self.max_tries:
                    Window.alert("It looks like there's a connection problem. We're sorry about the inconvenience. Please try again later.")
                    self.cancel()
                    return

                if populate_book_details():
                    self.cancel()
        
        populate_book_details = self.populate_book_details
        st = SpinTimer()