Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Toggl Button Core Components
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Toggl Button for Firefox
Toggl Button Core Components
Commits
ebd09e66
Commit
ebd09e66
authored
9 years ago
by
jurgenhaas
Browse files
Options
Downloads
Patches
Plain Diff
initial commit
parents
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
TogglLibrary.css
+147
-0
147 additions, 0 deletions
TogglLibrary.css
TogglLibrary.js
+606
-0
606 additions, 0 deletions
TogglLibrary.js
with
753 additions
and
0 deletions
TogglLibrary.css
0 → 100644
+
147
−
0
View file @
ebd09e66
/*------------------------------------------------------------------------
* CSS Library for Toggl-Button for Greasemonkey
*
* (c) Jürgen Haas
* Version: 1.3
*
* @see https://github.com/jurgenhaas/toggl-button-greasemonkey
*------------------------------------------------------------------------
*/
#toggl-button-gi-wrapper
{
position
:
fixed
;
bottom
:
10px
;
right
:
10px
;
z-index
:
9
;
display
:
none
;
padding
:
0
0
0
30px
;
border
:
1px
solid
#999999
;
-moz-box-shadow
:
0
0
5px
5px
#888
;
-webkit-box-shadow
:
0
0
5px
5px
#888
;
box-shadow
:
0
0
5px
5px
#888
;
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFa9AABWvQE1bkh1AAAAB3RJTUUH3QQeBxszNJufNAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAANsSURBVDjLrZRPaFxVFMZ/57735s1LMzMxmca0nQRCqkmTmgZSUUs1BYM70YK4CCgKunTRvQsVXRZD92rdCEWKiyhoFWOKFRFsWg1pMW1jpyltJpNkJvMv781797pI86zSShfe1eWecz++7zt/4H88cr/ANNhd3f2dKmnlxEpkmhJpKzIra/XS0jdLS6V3QT8ImMwPDAwl7eRRUda4KOkzSItgtDGmHEVmrqmjrwrV9amxfP7WfcGmwe4ZHHnRcqy3RNSTiDgiEucYYwyA1rrqR9GXa74/eWhh/pd7gcnC4MhLtmO/o5TadzeIlduDrlYxpXKcbLSO6mF05maj/vb41cvnAazt4PzA8H43Yb+nlDV6N5CkU6ReexVJpQivXgO9ZZWIKEek1xZx9vrOuTP+RsPalpftyr1p2WpCRNkAKEXi4CjuwVESg/sQ28bavQtdq2HK5RhQRHKtLnMn14qXFUBXf3+nWDIO4mwzcg89ResrE6i2DIQhJghwHn2E1BuvY+X2xHITIh2enRg/Bp4CUFYyJ0LftjxJp/CeGye48Bu1019gggBdWKHyyaeIskgeGQOl7vggyrPUY93ZnjYFIEoygrTEhu/ciZXtYPPcT9DYBGPAGPSt2/gXLuLs7QPXjdkpkXbPjVptAB1F2ti2/tv1O7cowoQhjbM/Et1ejt9QChHBxC2DrosYBdAMddEYKW/3UVRcRZfKuE88DsDmd9/T/H0O1f4QieH9hIt/Ynw/ZrapdaEYBBUboNIo3/Bcd04puxfAlEo0pn9gxwvPI46DP3sRafHwnj6MeC1szpzdYghoo6NS0/91tlAoWQC5jQ1/MNuZsix1RIlyAcLreUy9TmLkAN4zh3GHhohWV6l9fppw4Uo8EZUwzM/Vyic+3Nj4I7Zppqdn18PpjuOebb8sSsXNLK2tqEwaE0Xo9XXwg1heEEX1xXrtxPsLlz6YgWr86WS5XJ3ItN+wldXtiPSKyFbtgwBTqWCqtViaMcY0tW4sNRqnpgrFyVN+bfkf4wTw0drKzaOplku2WI4IOQXJfy8DY0xYicLrS43Gx1OF4uRkuXDtP/fZ8XS6/UB291jGtZ91lT2sRNoN6E0dLa83g/OLfv3bz/L5n2eg+kDLEeAYeN3ZbFsimdzh+1CsB5XZWqH0Nfj3yv8LMvl8kMnBqycAAAAASUVORK5CYII=)
no-repeat
left
top
;
background-color
:
#ffffff
;
font-size
:
12px
;
font-family
:
sans-serif
;
}
#toggl-button-gi-wrapper
.active
{
display
:
block
;
}
#toggl-button-gi-wrapper
:hover
{
cursor
:
pointer
;
}
#toggl-button-gi-wrapper
.collapsed
{
width
:
20px
;
height
:
20px
;
overflow
:
hidden
;
padding
:
0
;
}
#toggl-button-gi-wrapper
div
.content
{
margin
:
0
;
padding
:
2px
;
min-height
:
0
;
color
:
#000
;
}
#toggl-button-gi-wrapper
.collapsed
div
.content
{
display
:
none
;
}
#toggl-button-gi-wrapper
div
div
{
display
:
inline-block
;
margin
:
0
2px
;
}
#toggl-button-gi-wrapper
div
.project
{
font-weight
:
bold
;
background
:
none
;
}
.toggl-button-active
#toggl-button-gi-wrapper
{
display
:
none
;
}
#toggl-button-wrapper
{
position
:
fixed
;
bottom
:
10px
;
left
:
10px
;
z-index
:
999
;
padding
:
0
;
border
:
1px
solid
#999999
;
-moz-box-shadow
:
0
0
5px
5px
#888
;
-webkit-box-shadow
:
0
0
5px
5px
#888
;
box-shadow
:
0
0
5px
5px
#888
;
font-size
:
12px
;
font-family
:
sans-serif
;
}
#toggl-button-wrapper
.content
{
background-color
:
#dddddd
;
padding
:
0
;
margin
:
0
;
}
#toggl-button-wrapper
.content
.toggl-button-project-select
{
border
:
none
;
}
.toggl-button
{
display
:
inline-block
!important
;
line-height
:
20px
;
padding-left
:
23px
;
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFa9AABWvQE1bkh1AAAAB3RJTUUH3QQeBxszNJufNAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAANsSURBVDjLrZRPaFxVFMZ/57735s1LMzMxmca0nQRCqkmTmgZSUUs1BYM70YK4CCgKunTRvQsVXRZD92rdCEWKiyhoFWOKFRFsWg1pMW1jpyltJpNkJvMv781797pI86zSShfe1eWecz++7zt/4H88cr/ANNhd3f2dKmnlxEpkmhJpKzIra/XS0jdLS6V3QT8ImMwPDAwl7eRRUda4KOkzSItgtDGmHEVmrqmjrwrV9amxfP7WfcGmwe4ZHHnRcqy3RNSTiDgiEucYYwyA1rrqR9GXa74/eWhh/pd7gcnC4MhLtmO/o5TadzeIlduDrlYxpXKcbLSO6mF05maj/vb41cvnAazt4PzA8H43Yb+nlDV6N5CkU6ReexVJpQivXgO9ZZWIKEek1xZx9vrOuTP+RsPalpftyr1p2WpCRNkAKEXi4CjuwVESg/sQ28bavQtdq2HK5RhQRHKtLnMn14qXFUBXf3+nWDIO4mwzcg89ResrE6i2DIQhJghwHn2E1BuvY+X2xHITIh2enRg/Bp4CUFYyJ0LftjxJp/CeGye48Bu1019gggBdWKHyyaeIskgeGQOl7vggyrPUY93ZnjYFIEoygrTEhu/ciZXtYPPcT9DYBGPAGPSt2/gXLuLs7QPXjdkpkXbPjVptAB1F2ti2/tv1O7cowoQhjbM/Et1ejt9QChHBxC2DrosYBdAMddEYKW/3UVRcRZfKuE88DsDmd9/T/H0O1f4QieH9hIt/Ynw/ZrapdaEYBBUboNIo3/Bcd04puxfAlEo0pn9gxwvPI46DP3sRafHwnj6MeC1szpzdYghoo6NS0/91tlAoWQC5jQ1/MNuZsix1RIlyAcLreUy9TmLkAN4zh3GHhohWV6l9fppw4Uo8EZUwzM/Vyic+3Nj4I7Zppqdn18PpjuOebb8sSsXNLK2tqEwaE0Xo9XXwg1heEEX1xXrtxPsLlz6YgWr86WS5XJ3ItN+wldXtiPSKyFbtgwBTqWCqtViaMcY0tW4sNRqnpgrFyVN+bfkf4wTw0drKzaOplku2WI4IOQXJfy8DY0xYicLrS43Gx1OF4uRkuXDtP/fZ8XS6/UB291jGtZ91lT2sRNoN6E0dLa83g/OLfv3bz/L5n2eg+kDLEeAYeN3ZbFsimdzh+1CsB5XZWqH0Nfj3yv8LMvl8kMnBqycAAAAASUVORK5CYII=)
no-repeat
left
top
;
}
.toggl-button.hidden
{
display
:
none
!important
;
}
.toggl-button.min
{
height
:
19px
;
padding-left
:
19px
;
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAABIklEQVR4AYWSu0qDURCEN80fkUCwSCPk8iJ5DF/BF1Aw1Ye2NhpLQSwFn8EiMd4qb6WNEDCkEdIETVLogDm7RyzMMvwzO8ue4eRY/GiyQ583ZsKleBNLlcgqh8z5yku6q342VuM+7LzUr6WxgrvMmHAuuJZX/hk7kIh6xoSsI9+MBotIo4QnmJAlld8ydl1OaVPhFBMq4lN39owrF9us87o89EV8y50bY+SrqxxHNvGqx3k3Zks6lP2UjT1iDNO+2DahRC+7kJ70JLYNPEGbjbgG8bbza6Pj4paCTcZiY30L6eR0jDofLi9oUGJNaIin7id1w9gXjavscyYsoiffDKMc/+nfkrfy/wt5kPfrvXX9oAhwFO8tqkWHASPmwkC8Fd430YaitSJltegAAAAASUVORK5CYII=)
no-repeat
left
top
;
}
.toggl-button.min.active
{
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFa9AABWvQE1bkh1AAAAB3RJTUUH3QQeBxszNJufNAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAANsSURBVDjLrZRPaFxVFMZ/57735s1LMzMxmca0nQRCqkmTmgZSUUs1BYM70YK4CCgKunTRvQsVXRZD92rdCEWKiyhoFWOKFRFsWg1pMW1jpyltJpNkJvMv781797pI86zSShfe1eWecz++7zt/4H88cr/ANNhd3f2dKmnlxEpkmhJpKzIra/XS0jdLS6V3QT8ImMwPDAwl7eRRUda4KOkzSItgtDGmHEVmrqmjrwrV9amxfP7WfcGmwe4ZHHnRcqy3RNSTiDgiEucYYwyA1rrqR9GXa74/eWhh/pd7gcnC4MhLtmO/o5TadzeIlduDrlYxpXKcbLSO6mF05maj/vb41cvnAazt4PzA8H43Yb+nlDV6N5CkU6ReexVJpQivXgO9ZZWIKEek1xZx9vrOuTP+RsPalpftyr1p2WpCRNkAKEXi4CjuwVESg/sQ28bavQtdq2HK5RhQRHKtLnMn14qXFUBXf3+nWDIO4mwzcg89ResrE6i2DIQhJghwHn2E1BuvY+X2xHITIh2enRg/Bp4CUFYyJ0LftjxJp/CeGye48Bu1019gggBdWKHyyaeIskgeGQOl7vggyrPUY93ZnjYFIEoygrTEhu/ciZXtYPPcT9DYBGPAGPSt2/gXLuLs7QPXjdkpkXbPjVptAB1F2ti2/tv1O7cowoQhjbM/Et1ejt9QChHBxC2DrosYBdAMddEYKW/3UVRcRZfKuE88DsDmd9/T/H0O1f4QieH9hIt/Ynw/ZrapdaEYBBUboNIo3/Bcd04puxfAlEo0pn9gxwvPI46DP3sRafHwnj6MeC1szpzdYghoo6NS0/91tlAoWQC5jQ1/MNuZsix1RIlyAcLreUy9TmLkAN4zh3GHhohWV6l9fppw4Uo8EZUwzM/Vyic+3Nj4I7Zppqdn18PpjuOebb8sSsXNLK2tqEwaE0Xo9XXwg1heEEX1xXrtxPsLlz6YgWr86WS5XJ3ItN+wldXtiPSKyFbtgwBTqWCqtViaMcY0tW4sNRqnpgrFyVN+bfkf4wTw0drKzaOplku2WI4IOQXJfy8DY0xYicLrS43Gx1OF4uRkuXDtP/fZ8XS6/UB291jGtZ91lT2sRNoN6E0dLa83g/OLfv3bz/L5n2eg+kDLEeAYeN3ZbFsimdzh+1CsB5XZWqH0Nfj3yv8LMvl8kMnBqycAAAAASUVORK5CYII=)
no-repeat
left
top
;
}
.toggl-button-project-select
{
display
:
inline-block
;
width
:
150px
;
height
:
14px
;
line-height
:
0
;
overflow
:
hidden
;
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAABIklEQVR4AYWSu0qDURCEN80fkUCwSCPk8iJ5DF/BF1Aw1Ye2NhpLQSwFn8EiMd4qb6WNEDCkEdIETVLogDm7RyzMMvwzO8ue4eRY/GiyQ583ZsKleBNLlcgqh8z5yku6q342VuM+7LzUr6WxgrvMmHAuuJZX/hk7kIh6xoSsI9+MBotIo4QnmJAlld8ydl1OaVPhFBMq4lN39owrF9us87o89EV8y50bY+SrqxxHNvGqx3k3Zks6lP2UjT1iDNO+2DahRC+7kJ70JLYNPEGbjbgG8bbza6Pj4paCTcZiY30L6eR0jDofLi9oUGJNaIin7id1w9gXjavscyYsoiffDKMc/+nfkrfy/wt5kPfrvXX9oAhwFO8tqkWHASPmwkC8Fd430YaitSJltegAAAAASUVORK5CYII=)
no-repeat
right
#ddd
;
border
:
1px
solid
#ccc
;
margin-left
:
5px
;
}
.toggl-button-project-select
select
{
background
:
transparent
;
width
:
268px
;
padding
:
0
2px
;
font-size
:
10px
;
line-height
:
1em
;
border
:
0
;
border-radius
:
0
;
height
:
12px
;
-webkit-appearance
:
none
;
}
#toggl-button-auth-failed
{
display
:
block
;
position
:
fixed
;
z-index
:
999
;
top
:
0
;
left
:
0
;
right
:
0
;
height
:
25px
;
padding
:
5px
;
background-color
:
#ff0000
;
color
:
#ffffff
;
text-align
:
center
;
font-weight
:
bold
;
}
#toggl-button-auth-failed
.content
{
display
:
inline-block
;
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAABIklEQVR4AYWSu0qDURCEN80fkUCwSCPk8iJ5DF/BF1Aw1Ye2NhpLQSwFn8EiMd4qb6WNEDCkEdIETVLogDm7RyzMMvwzO8ue4eRY/GiyQ583ZsKleBNLlcgqh8z5yku6q342VuM+7LzUr6WxgrvMmHAuuJZX/hk7kIh6xoSsI9+MBotIo4QnmJAlld8ydl1OaVPhFBMq4lN39owrF9us87o89EV8y50bY+SrqxxHNvGqx3k3Zks6lP2UjT1iDNO+2DahRC+7kJ70JLYNPEGbjbgG8bbza6Pj4paCTcZiY30L6eR0jDofLi9oUGJNaIin7id1w9gXjavscyYsoiffDKMc/+nfkrfy/wt5kPfrvXX9oAhwFO8tqkWHASPmwkC8Fd430YaitSJltegAAAAASUVORK5CYII=)
no-repeat
left
top
;
padding-left
:
35px
;
}
#toggl-button-auth-failed
.content
a
{
padding-left
:
10px
;
color
:
#ffffff
;
text-decoration
:
underline
;
}
/* Special positioning on TeamWork */
body
#tasks
#toggl-button-wrapper
{
bottom
:
40px
;
}
This diff is collapsed.
Click to expand it.
TogglLibrary.js
0 → 100644
+
606
−
0
View file @
ebd09e66
/*------------------------------------------------------------------------
* JavaScript Library for Toggl-Button for Greasemonkey
*
* (c) Jürgen Haas
* Version: 1.3
*
* @see https://github.com/jurgenhaas/toggl-button-greasemonkey
*------------------------------------------------------------------------
*/
function
TogglButtonGM
(
selector
,
renderer
)
{
var
$activeApiUrl
=
null
,
$apiUrl
=
"
https://www.toggl.com/api/v7
"
,
$newApiUrl
=
"
https://www.toggl.com/api/v8
"
,
$legacyApiUrl
=
"
https://new.toggl.com/api/v8
"
,
$triedAlternative
=
false
,
$api_token
=
null
,
$default_wid
=
null
,
$clientMap
=
{},
$projectMap
=
{},
$instances
=
{};
init
(
selector
,
renderer
);
function
init
(
selector
,
renderer
,
apiUrl
)
{
var
timeNow
=
new
Date
().
getTime
(),
timeAuth
=
GM_getValue
(
'
_authenticated
'
,
0
);
apiUrl
=
apiUrl
||
$newApiUrl
;
$api_token
=
GM_getValue
(
'
_api_token
'
,
false
);
if
(
$api_token
&&
(
timeNow
-
timeAuth
)
<
(
6
*
60
*
60
*
1000
))
{
$activeApiUrl
=
GM_getValue
(
'
_api_url
'
,
$newApiUrl
);
$default_wid
=
GM_getValue
(
'
_default_wid
'
,
0
);
$clientMap
=
JSON
.
parse
(
GM_getValue
(
'
_clientMap
'
,
{}));
$projectMap
=
JSON
.
parse
(
GM_getValue
(
'
_projectMap
'
,
{}));
if
(
$activeApiUrl
==
$legacyApiUrl
)
{
// See issue #22.
$activeApiUrl
=
$newApiUrl
;
GM_setValue
(
'
_api_url
'
,
$activeApiUrl
);
}
render
(
selector
,
renderer
);
return
;
}
var
headers
=
{};
if
(
$api_token
)
{
headers
=
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
};
}
$activeApiUrl
=
apiUrl
;
GM_xmlhttpRequest
({
method
:
"
GET
"
,
url
:
apiUrl
+
"
/me?with_related_data=true
"
,
headers
:
headers
,
onload
:
function
(
result
)
{
if
(
result
.
status
===
200
)
{
var
resp
=
JSON
.
parse
(
result
.
responseText
);
$clientMap
[
0
]
=
'
No Client
'
;
if
(
resp
.
data
.
clients
)
{
resp
.
data
.
clients
.
forEach
(
function
(
client
)
{
$clientMap
[
client
.
id
]
=
client
.
name
;
});
}
if
(
resp
.
data
.
projects
)
{
resp
.
data
.
projects
.
forEach
(
function
(
project
)
{
if
(
$clientMap
[
project
.
cid
]
==
undefined
)
{
project
.
cid
=
0
;
}
if
(
project
.
active
)
{
$projectMap
[
project
.
id
]
=
{
id
:
project
.
id
,
cid
:
project
.
cid
,
name
:
project
.
name
,
billable
:
project
.
billable
};
}
});
}
GM_setValue
(
'
_authenticated
'
,
new
Date
().
getTime
());
GM_setValue
(
'
_api_token
'
,
resp
.
data
.
api_token
);
GM_setValue
(
'
_api_url
'
,
$activeApiUrl
);
GM_setValue
(
'
_default_wid
'
,
resp
.
data
.
default_wid
);
GM_setValue
(
'
_clientMap
'
,
JSON
.
stringify
(
$clientMap
));
GM_setValue
(
'
_projectMap
'
,
JSON
.
stringify
(
$projectMap
));
$api_token
=
resp
.
data
.
api_token
;
$default_wid
=
resp
.
data
.
default_wid
;
render
(
selector
,
renderer
);
}
else
if
(
!
$triedAlternative
)
{
$triedAlternative
=
true
;
if
(
apiUrl
===
$apiUrl
)
{
init
(
selector
,
renderer
,
$newApiUrl
);
}
else
if
(
apiUrl
===
$newApiUrl
)
{
init
(
selector
,
renderer
,
$apiUrl
);
}
}
else
if
(
$api_token
)
{
// Delete the API token and try again
GM_setValue
(
'
_api_token
'
,
false
);
$triedAlternative
=
false
;
init
(
selector
,
renderer
,
$newApiUrl
);
}
else
{
var
wrapper
=
document
.
createElement
(
'
div
'
),
content
=
createTag
(
'
div
'
,
'
content
'
),
link
=
createLink
(
'
login
'
,
'
a
'
,
'
https://new.toggl.com/
'
,
'
Login
'
);
GM_addStyle
(
GM_getResourceText
(
'
togglStyle
'
));
link
.
setAttribute
(
'
target
'
,
'
_blank
'
);
wrapper
.
setAttribute
(
'
id
'
,
'
toggl-button-auth-failed
'
);
content
.
appendChild
(
document
.
createTextNode
(
'
Authorization to your Toggl account failed!
'
));
content
.
appendChild
(
link
);
wrapper
.
appendChild
(
content
);
document
.
querySelector
(
'
body
'
).
appendChild
(
wrapper
);
}
}
});
}
function
render
(
selector
,
renderer
)
{
if
(
selector
==
null
)
{
return
;
}
var
i
,
len
,
elems
=
document
.
querySelectorAll
(
selector
);
for
(
i
=
0
,
len
=
elems
.
length
;
i
<
len
;
i
+=
1
)
{
elems
[
i
].
classList
.
add
(
'
toggl
'
);
$instances
[
i
]
=
new
TogglButtonGMInstance
(
renderer
(
elems
[
i
]));
}
document
.
addEventListener
(
'
TogglButtonGMUpdateStatus
'
,
function
()
{
GM_xmlhttpRequest
({
method
:
"
GET
"
,
url
:
$activeApiUrl
+
"
/time_entries/current
"
,
headers
:
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
},
onload
:
function
(
result
)
{
if
(
result
.
status
===
200
)
{
var
resp
=
JSON
.
parse
(
result
.
responseText
),
data
=
resp
.
data
||
false
;
if
(
data
)
{
for
(
i
in
$instances
)
{
$instances
[
i
].
checkCurrentLinkStatus
(
data
);
}
}
}
}
});
});
window
.
addEventListener
(
'
focus
'
,
function
()
{
document
.
dispatchEvent
(
new
CustomEvent
(
'
TogglButtonGMUpdateStatus
'
));
});
}
this
.
clickLinks
=
function
()
{
for
(
i
in
$instances
)
{
$instances
[
i
].
clickLink
();
}
};
this
.
getCurrentTimeEntry
=
function
(
callback
)
{
GM_xmlhttpRequest
({
method
:
"
GET
"
,
url
:
$activeApiUrl
+
"
/time_entries/current
"
,
headers
:
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
},
onload
:
function
(
result
)
{
if
(
result
.
status
===
200
)
{
var
resp
=
JSON
.
parse
(
result
.
responseText
),
data
=
resp
.
data
||
false
;
if
(
data
)
{
callback
(
data
.
id
,
true
);
}
}
}
});
};
this
.
stopTimeEntry
=
function
(
entryId
,
asCallback
)
{
if
(
entryId
==
null
)
{
if
(
asCallback
)
{
return
;
}
this
.
getCurrentTimeEntry
(
this
.
stopTimeEntry
);
return
;
}
GM_xmlhttpRequest
({
method
:
"
PUT
"
,
url
:
$activeApiUrl
+
"
/time_entries/
"
+
entryId
+
"
/stop
"
,
headers
:
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
},
onload
:
function
()
{
document
.
dispatchEvent
(
new
CustomEvent
(
'
TogglButtonGMUpdateStatus
'
));
}
});
};
function
TogglButtonGMInstance
(
params
)
{
var
$curEntryId
=
null
,
$isStarted
=
false
,
$link
=
null
,
$generalInfo
=
null
,
$buttonTypeMinimal
=
false
,
$projectSelector
=
window
.
location
.
host
,
$projectId
=
null
,
$projectSelected
=
false
,
$projectSelectElem
=
null
,
$stopCallback
=
null
;
this
.
checkCurrentLinkStatus
=
function
(
data
)
{
var
started
,
updateRequired
=
false
;
if
(
!
data
)
{
if
(
$isStarted
)
{
updateRequired
=
true
;
started
=
false
;
}
}
else
{
if
(
$generalInfo
!=
null
)
{
if
(
!
$isStarted
||
(
$curEntryId
!=
null
&&
$curEntryId
!=
data
.
id
))
{
$curEntryId
=
data
.
id
;
$isStarted
=
false
;
}
}
if
(
$curEntryId
==
data
.
id
)
{
if
(
!
$isStarted
)
{
updateRequired
=
true
;
started
=
true
;
}
}
else
{
if
(
$isStarted
)
{
updateRequired
=
true
;
started
=
false
;
}
}
}
if
(
updateRequired
)
{
if
(
!
started
)
{
$curEntryId
=
null
;
}
if
(
$link
!=
null
)
{
updateLink
(
started
);
}
if
(
$generalInfo
!=
null
)
{
if
(
data
)
{
var
projectName
=
'
No project
'
,
clientName
=
'
No client
'
;
if
(
data
.
pid
!==
undefined
)
{
if
(
$projectMap
[
data
.
pid
]
==
undefined
)
{
GM_setValue
(
'
_authenticated
'
,
0
);
window
.
location
.
reload
();
return
;
}
projectName
=
$projectMap
[
data
.
pid
].
name
;
clientName
=
$clientMap
[
$projectMap
[
data
.
pid
].
cid
];
}
var
content
=
createTag
(
'
div
'
,
'
content
'
),
contentClient
=
createTag
(
'
div
'
,
'
client
'
),
contentProject
=
createTag
(
'
div
'
,
'
project
'
),
contentDescription
=
createTag
(
'
div
'
,
'
description
'
);
contentClient
.
innerHTML
=
clientName
;
contentProject
.
innerHTML
=
projectName
;
contentDescription
.
innerHTML
=
data
.
description
;
content
.
appendChild
(
contentClient
);
content
.
appendChild
(
contentProject
);
content
.
appendChild
(
contentDescription
);
while
(
$generalInfo
.
firstChild
)
{
$generalInfo
.
removeChild
(
$generalInfo
.
firstChild
);
}
$generalInfo
.
appendChild
(
content
);
}
updateGeneralInfo
(
started
);
}
}
};
this
.
clickLink
=
function
(
data
)
{
$link
.
dispatchEvent
(
new
CustomEvent
(
'
click
'
));
};
createTimerLink
(
params
);
function
createTimerLink
(
params
)
{
GM_addStyle
(
GM_getResourceText
(
'
togglStyle
'
));
if
(
params
.
generalMode
!==
undefined
&&
params
.
generalMode
)
{
$generalInfo
=
document
.
createElement
(
'
div
'
);
$generalInfo
.
id
=
'
toggl-button-gi-wrapper
'
;
$generalInfo
.
addEventListener
(
'
click
'
,
function
(
e
)
{
e
.
preventDefault
();
$generalInfo
.
classList
.
toggle
(
'
collapsed
'
);
});
document
.
querySelector
(
'
body
'
).
appendChild
(
$generalInfo
);
document
.
dispatchEvent
(
new
CustomEvent
(
'
TogglButtonGMUpdateStatus
'
));
return
;
}
if
(
params
.
projectIds
!==
undefined
)
{
$projectSelector
+=
'
-
'
+
params
.
projectIds
.
join
(
'
-
'
);
}
if
(
params
.
stopCallback
!==
undefined
)
{
$stopCallback
=
params
.
stopCallback
;
}
updateProjectId
();
$link
=
createLink
(
'
toggl-button
'
);
$link
.
classList
.
add
(
params
.
className
);
if
(
params
.
buttonType
===
'
minimal
'
)
{
$link
.
classList
.
add
(
'
min
'
);
$link
.
removeChild
(
$link
.
firstChild
);
$buttonTypeMinimal
=
true
;
}
$link
.
addEventListener
(
'
click
'
,
function
(
e
)
{
var
opts
=
''
;
e
.
preventDefault
();
if
(
$isStarted
)
{
stopTimeEntry
();
}
else
{
var
billable
=
false
;
if
(
$projectId
!=
undefined
&&
$projectId
>
0
)
{
billable
=
$projectMap
[
$projectId
].
billable
;
}
opts
=
{
$projectId
:
$projectId
||
null
,
billable
:
billable
,
description
:
invokeIfFunction
(
params
.
description
),
createdWith
:
'
TogglButtonGM -
'
+
params
.
className
};
createTimeEntry
(
opts
);
}
return
false
;
});
// new button created - reset state
$isStarted
=
false
;
// check if our link is the current time entry and set the state if it is
checkCurrentTimeEntry
({
$projectId
:
$projectId
,
description
:
invokeIfFunction
(
params
.
description
)
});
document
.
querySelector
(
'
body
'
).
classList
.
add
(
'
toggl-button-available
'
);
if
(
params
.
targetSelectors
==
undefined
)
{
var
wrapper
=
document
.
createElement
(
'
div
'
),
content
=
createTag
(
'
div
'
,
'
content
'
);
wrapper
.
id
=
'
toggl-button-wrapper
'
;
content
.
appendChild
(
$link
);
content
.
appendChild
(
createProjectSelect
());
wrapper
.
appendChild
(
content
);
document
.
querySelector
(
'
body
'
).
appendChild
(
wrapper
);
}
else
{
var
elem
=
params
.
targetSelectors
.
context
||
document
;
if
(
params
.
targetSelectors
.
link
!=
undefined
)
{
elem
.
querySelector
(
params
.
targetSelectors
.
link
).
appendChild
(
$link
);
}
if
(
params
.
targetSelectors
.
projectSelect
!=
undefined
)
{
elem
.
querySelector
(
params
.
targetSelectors
.
projectSelect
).
appendChild
(
createProjectSelect
());
}
}
return
$link
;
}
function
createTimeEntry
(
timeEntry
)
{
var
start
=
new
Date
();
GM_xmlhttpRequest
({
method
:
"
POST
"
,
url
:
$activeApiUrl
+
"
/time_entries
"
,
headers
:
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
},
data
:
JSON
.
stringify
({
time_entry
:
{
start
:
start
.
toISOString
(),
description
:
timeEntry
.
description
,
wid
:
$default_wid
,
pid
:
timeEntry
.
$projectId
||
null
,
billable
:
timeEntry
.
billable
||
false
,
duration
:
-
(
start
.
getTime
()
/
1000
),
created_with
:
timeEntry
.
createdWith
||
'
TogglButtonGM
'
}
}),
onload
:
function
(
res
)
{
var
responseData
,
entryId
;
responseData
=
JSON
.
parse
(
res
.
responseText
);
entryId
=
responseData
&&
responseData
.
data
&&
responseData
.
data
.
id
;
$curEntryId
=
entryId
;
document
.
dispatchEvent
(
new
CustomEvent
(
'
TogglButtonGMUpdateStatus
'
));
}
});
}
function
checkCurrentTimeEntry
(
params
)
{
GM_xmlhttpRequest
({
method
:
"
GET
"
,
url
:
$activeApiUrl
+
"
/time_entries/current
"
,
headers
:
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
},
onload
:
function
(
result
)
{
if
(
result
.
status
===
200
)
{
var
resp
=
JSON
.
parse
(
result
.
responseText
);
if
(
resp
==
null
)
{
return
;
}
if
(
params
.
description
===
resp
.
data
.
description
)
{
$curEntryId
=
resp
.
data
.
id
;
updateLink
(
true
);
}
}
}
});
}
function
stopTimeEntry
(
entryId
)
{
entryId
=
entryId
||
$curEntryId
;
if
(
!
entryId
)
{
return
;
}
GM_xmlhttpRequest
({
method
:
"
PUT
"
,
url
:
$activeApiUrl
+
"
/time_entries/
"
+
entryId
+
"
/stop
"
,
headers
:
{
"
Authorization
"
:
"
Basic
"
+
btoa
(
$api_token
+
'
:api_token
'
)
},
onload
:
function
(
result
)
{
document
.
dispatchEvent
(
new
CustomEvent
(
'
TogglButtonGMUpdateStatus
'
));
if
(
result
.
status
===
200
)
{
var
resp
=
JSON
.
parse
(
result
.
responseText
),
data
=
resp
.
data
||
false
;
if
(
data
)
{
if
(
$stopCallback
!==
undefined
)
{
var
currentdate
=
new
Date
();
$stopCallback
((
currentdate
.
getTime
()
-
(
data
.
duration
*
1000
)),
data
.
duration
);
}
}
}
}
});
}
function
createTag
(
name
,
className
,
innerHTML
)
{
var
tag
=
document
.
createElement
(
name
);
tag
.
className
=
className
;
if
(
innerHTML
)
{
tag
.
innerHTML
=
innerHTML
;
}
return
tag
;
}
function
createLink
(
className
,
tagName
,
linkHref
,
linkText
)
{
// Param defaults
tagName
=
tagName
||
'
a
'
;
linkHref
=
linkHref
||
'
#
'
;
linkText
=
linkText
||
'
Start timer
'
;
var
link
=
createTag
(
tagName
,
className
);
if
(
tagName
===
'
a
'
)
{
link
.
setAttribute
(
'
href
'
,
linkHref
);
}
link
.
appendChild
(
document
.
createTextNode
(
linkText
));
return
link
;
}
function
updateGeneralInfo
(
started
)
{
if
(
started
)
{
$generalInfo
.
classList
.
add
(
'
active
'
);
}
else
{
$generalInfo
.
classList
.
remove
(
'
active
'
);
}
$isStarted
=
started
;
}
function
updateLink
(
started
)
{
var
linkText
,
color
=
''
;
if
(
started
)
{
document
.
querySelector
(
'
body
'
).
classList
.
add
(
'
toggl-button-active
'
);
$link
.
classList
.
add
(
'
active
'
);
color
=
'
#1ab351
'
;
linkText
=
'
Stop timer
'
;
}
else
{
document
.
querySelector
(
'
body
'
).
classList
.
remove
(
'
toggl-button-active
'
);
$link
.
classList
.
remove
(
'
active
'
);
linkText
=
'
Start timer
'
;
}
$isStarted
=
started
;
$link
.
setAttribute
(
'
style
'
,
'
color:
'
+
color
+
'
;
'
);
if
(
!
$buttonTypeMinimal
)
{
$link
.
innerHTML
=
linkText
;
}
$projectSelectElem
.
disabled
=
$isStarted
;
}
function
updateProjectId
(
id
)
{
id
=
id
||
GM_getValue
(
$projectSelector
,
0
);
$projectSelected
=
(
id
!=
0
);
if
(
id
<=
0
)
{
$projectId
=
null
;
}
else
{
$projectId
=
id
;
}
if
(
$projectSelectElem
!=
undefined
)
{
$projectSelectElem
.
value
=
id
;
$projectSelectElem
.
disabled
=
$isStarted
;
}
GM_setValue
(
$projectSelector
,
id
);
if
(
$link
!=
undefined
)
{
if
(
$projectSelected
)
{
$link
.
classList
.
remove
(
'
hidden
'
);
}
else
{
$link
.
classList
.
add
(
'
hidden
'
);
}
}
}
function
invokeIfFunction
(
trial
)
{
if
(
trial
instanceof
Function
)
{
return
trial
();
}
return
trial
;
}
function
createProjectSelect
()
{
var
pid
,
wrapper
=
createTag
(
'
div
'
,
'
toggl-button-project-select
'
),
noneOptionAdded
=
false
,
noneOption
=
document
.
createElement
(
'
option
'
),
emptyOption
=
document
.
createElement
(
'
option
'
),
resetOption
=
document
.
createElement
(
'
option
'
);
$projectSelectElem
=
createTag
(
'
select
'
);
// None Option to indicate that a project should be selected first
if
(
!
$projectSelected
)
{
noneOption
.
setAttribute
(
'
value
'
,
'
0
'
);
noneOption
.
text
=
'
- First select a project -
'
;
$projectSelectElem
.
appendChild
(
noneOption
);
noneOptionAdded
=
true
;
}
// Empty Option for tasks with no project
emptyOption
.
setAttribute
(
'
value
'
,
'
-1
'
);
emptyOption
.
text
=
'
No Project
'
;
$projectSelectElem
.
appendChild
(
emptyOption
);
var
optgroup
,
project
,
clientMap
=
[];
for
(
pid
in
$projectMap
)
{
//noinspection JSUnfilteredForInLoop
project
=
$projectMap
[
pid
];
if
(
clientMap
[
project
.
cid
]
==
undefined
)
{
optgroup
=
createTag
(
'
optgroup
'
);
optgroup
.
label
=
$clientMap
[
project
.
cid
];
clientMap
[
project
.
cid
]
=
optgroup
;
$projectSelectElem
.
appendChild
(
optgroup
);
}
else
{
optgroup
=
clientMap
[
project
.
cid
];
}
var
option
=
document
.
createElement
(
'
option
'
);
option
.
setAttribute
(
'
value
'
,
project
.
id
);
option
.
text
=
project
.
name
;
optgroup
.
appendChild
(
option
);
}
// Reset Option to reload settings and projects from Toggl
resetOption
.
setAttribute
(
'
value
'
,
'
RESET
'
);
resetOption
.
text
=
'
Reload settings
'
;
$projectSelectElem
.
appendChild
(
resetOption
);
$projectSelectElem
.
addEventListener
(
'
change
'
,
function
()
{
if
(
$projectSelectElem
.
value
==
'
RESET
'
)
{
GM_setValue
(
'
_authenticated
'
,
0
);
window
.
location
.
reload
();
return
;
}
if
(
noneOptionAdded
)
{
$projectSelectElem
.
removeChild
(
noneOption
);
noneOptionAdded
=
false
;
}
updateProjectId
(
$projectSelectElem
.
value
);
});
updateProjectId
(
$projectId
);
wrapper
.
appendChild
(
$projectSelectElem
);
return
wrapper
;
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment