| @@ -235,6 +235,8 @@ migrate_type_helper = This repository will be a <span class="label label-blue la | |||
| migrate_repo = Migrate Repository | |||
| copy_link = Copy | |||
| click_to_copy = Copy to clipboard | |||
| copied = Copied OK | |||
| clone_helper = Need help cloning? Visit <a target="_blank" href="http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository">Help</a>! | |||
| unwatch = Unwatch | |||
| watch = Watch | |||
| @@ -235,6 +235,8 @@ migrate_type_helper = 本仓库将是 <span class="label label-blue label-radius | |||
| migrate_repo = 迁移仓库 | |||
| copy_link = 复制链接 | |||
| click_to_copy = 复制到剪切板 | |||
| copied = 复制成功 | |||
| clone_helper = 不知道如何操作?访问 <a target="_blank" href="http://git-scm.com/book/zh/Git-基础-取得项目的-Git-仓库">此处</a> 查看帮助! | |||
| unwatch = 取消关注 | |||
| watch = 关注 | |||
| @@ -0,0 +1,25 @@ | |||
| .tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; } | |||
| .tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; } | |||
| /* Rounded corners */ | |||
| .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } | |||
| /* Uncomment for shadow */ | |||
| /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/ | |||
| .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } | |||
| /* Rules to colour arrows */ | |||
| .tipsy-arrow-n { border-bottom-color: #000; } | |||
| .tipsy-arrow-s { border-top-color: #000; } | |||
| .tipsy-arrow-e { border-left-color: #000; } | |||
| .tipsy-arrow-w { border-right-color: #000; } | |||
| .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } | |||
| .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} | |||
| .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} | |||
| .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |||
| .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |||
| .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |||
| .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } | |||
| .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } | |||
| @@ -1,6 +1,7 @@ | |||
| // @codekit-prepend "lib/jquery-1.11.1.min.js" | |||
| // @codekit-prepend "lib/lib.js" | |||
| // @codekit-prepend "lib/tabs.js" | |||
| // @codekit-prepend "lib/jquery.tipsy.js" | |||
| var Gogs = {}; | |||
| @@ -202,7 +203,7 @@ var Gogs = {}; | |||
| // Search users by keyword. | |||
| Gogs.searchUsers = function (val, $target) { | |||
| $.ajax({ | |||
| url: Gogs.AppRootSubUrl + '/api/v1/users/search?q=' + val, | |||
| url: Gogs.AppSubUrl + '/api/v1/users/search?q=' + val, | |||
| dataType: "json", | |||
| success: function (json) { | |||
| if (json.ok && json.data.length) { | |||
| @@ -222,7 +223,7 @@ var Gogs = {}; | |||
| // Search repositories by keyword. | |||
| Gogs.searchRepos = function (val, $target, $param) { | |||
| $.ajax({ | |||
| url: Gogs.AppRootSubUrl + '/api/v1/repos/search?q=' + val + '&' + $param, | |||
| url: Gogs.AppSubUrl + '/api/v1/repos/search?q=' + val + '&' + $param, | |||
| dataType: "json", | |||
| success: function (json) { | |||
| if (json.ok && json.data.length) { | |||
| @@ -245,7 +246,7 @@ var Gogs = {}; | |||
| return; | |||
| } | |||
| $(selector).zclip({ | |||
| path: Gogs.AppRootSubUrl + "/js/ZeroClipboard.swf", | |||
| path: Gogs.AppSubUrl + "/js/ZeroClipboard.swf", | |||
| copy: function () { | |||
| var t = $(this).data("copy-val"); | |||
| var to = $($(this).data("copy-from")); | |||
| @@ -262,17 +263,14 @@ var Gogs = {}; | |||
| return str; | |||
| }, | |||
| afterCopy: function () { | |||
| alert("Clone URL has copied!"); | |||
| // var $this = $(this); | |||
| // $this.tooltip('hide') | |||
| // .attr('data-original-title', 'Copied OK'); | |||
| // setTimeout(function () { | |||
| // $this.tooltip("show"); | |||
| // }, 200); | |||
| // setTimeout(function () { | |||
| // $this.tooltip('hide') | |||
| // .attr('data-original-title', 'Copy to Clipboard'); | |||
| // }, 3000); | |||
| var $this = $(this); | |||
| $this.tipsy("hide").attr('original-title', $this.data('after-title')); | |||
| setTimeout(function () { | |||
| $this.tipsy("show"); | |||
| }, 200); | |||
| setTimeout(function () { | |||
| $this.tipsy('hide').attr('original-title', $this.data('original-title')); | |||
| }, 3000); | |||
| } | |||
| }).addClass("js-copy-bind"); | |||
| } | |||
| @@ -344,26 +342,30 @@ function initRepo() { | |||
| $('.clone-url').text($(this).data('link')) | |||
| }); | |||
| // Copy URL. | |||
| $('#repo-clone-copy').hover(function () { | |||
| var $clone_btn = $('#repo-clone-copy'); | |||
| $clone_btn.hover(function () { | |||
| Gogs.bindCopy($(this)); | |||
| }) | |||
| $clone_btn.tipsy({ | |||
| fade: true | |||
| }); | |||
| } | |||
| // when user changes hook type, hide/show proper divs | |||
| function initHookTypeChange() { | |||
| // web hook type change | |||
| $('select#hook-type').on("change", function () { | |||
| hookTypes = ['Gogs','Slack']; | |||
| hookTypes = ['Gogs', 'Slack']; | |||
| var curHook = $(this).val(); | |||
| hookTypes.forEach(function(hookType) { | |||
| if (curHook === hookType) { | |||
| $('div#'+hookType.toLowerCase()).toggleShow(); | |||
| } | |||
| else { | |||
| $('div#'+hookType.toLowerCase()).toggleHide(); | |||
| } | |||
| }); | |||
| var curHook = $(this).val(); | |||
| hookTypes.forEach(function (hookType) { | |||
| if (curHook === hookType) { | |||
| $('div#' + hookType.toLowerCase()).toggleShow(); | |||
| } | |||
| else { | |||
| $('div#' + hookType.toLowerCase()).toggleHide(); | |||
| } | |||
| }); | |||
| }); | |||
| } | |||
| @@ -592,7 +594,7 @@ function initInstall() { | |||
| } | |||
| $(document).ready(function () { | |||
| Gogs.AppRootSubUrl = $('head').data('suburl'); | |||
| Gogs.AppSubUrl = $('head').data('suburl'); | |||
| initCore(); | |||
| if ($('#user-profile-setting').length) { | |||
| initUserSetting(); | |||
| @@ -645,7 +647,7 @@ function homepage() { | |||
| $('#promo-form').submit(function (e) { | |||
| if ($('#username').val() === "") { | |||
| e.preventDefault(); | |||
| window.location.href = Gogs.AppRootSubUrl + '/user/login'; | |||
| window.location.href = Gogs.AppSubUrl + '/user/login'; | |||
| return true | |||
| } | |||
| }); | |||
| @@ -653,9 +655,9 @@ function homepage() { | |||
| $('#register-button').click(function (e) { | |||
| if ($('#username').val() === "") { | |||
| e.preventDefault(); | |||
| window.location.href = Gogs.AppRootSubUrl + '/user/sign_up'; | |||
| window.location.href = Gogs.AppSubUrl + '/user/sign_up'; | |||
| return true | |||
| } | |||
| $('#promo-form').attr('action', Gogs.AppRootSubUrl + '/user/sign_up'); | |||
| $('#promo-form').attr('action', Gogs.AppSubUrl + '/user/sign_up'); | |||
| }); | |||
| } | |||
| @@ -0,0 +1,258 @@ | |||
| // tipsy, facebook style tooltips for jquery | |||
| // version 1.0.0a | |||
| // (c) 2008-2010 jason frame [jason@onehackoranother.com] | |||
| // released under the MIT license | |||
| (function($) { | |||
| function maybeCall(thing, ctx) { | |||
| return (typeof thing == 'function') ? (thing.call(ctx)) : thing; | |||
| }; | |||
| function isElementInDOM(ele) { | |||
| while (ele = ele.parentNode) { | |||
| if (ele == document) return true; | |||
| } | |||
| return false; | |||
| }; | |||
| function Tipsy(element, options) { | |||
| this.$element = $(element); | |||
| this.options = options; | |||
| this.enabled = true; | |||
| this.fixTitle(); | |||
| }; | |||
| Tipsy.prototype = { | |||
| show: function() { | |||
| var title = this.getTitle(); | |||
| if (title && this.enabled) { | |||
| var $tip = this.tip(); | |||
| $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); | |||
| $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity | |||
| $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body); | |||
| var pos = $.extend({}, this.$element.offset(), { | |||
| width: this.$element[0].offsetWidth, | |||
| height: this.$element[0].offsetHeight | |||
| }); | |||
| var actualWidth = $tip[0].offsetWidth, | |||
| actualHeight = $tip[0].offsetHeight, | |||
| gravity = maybeCall(this.options.gravity, this.$element[0]); | |||
| var tp; | |||
| switch (gravity.charAt(0)) { | |||
| case 'n': | |||
| tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; | |||
| break; | |||
| case 's': | |||
| tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; | |||
| break; | |||
| case 'e': | |||
| tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}; | |||
| break; | |||
| case 'w': | |||
| tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}; | |||
| break; | |||
| } | |||
| if (gravity.length == 2) { | |||
| if (gravity.charAt(1) == 'w') { | |||
| tp.left = pos.left + pos.width / 2 - 15; | |||
| } else { | |||
| tp.left = pos.left + pos.width / 2 - actualWidth + 15; | |||
| } | |||
| } | |||
| $tip.css(tp).addClass('tipsy-' + gravity); | |||
| $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0); | |||
| if (this.options.className) { | |||
| $tip.addClass(maybeCall(this.options.className, this.$element[0])); | |||
| } | |||
| if (this.options.fade) { | |||
| $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}); | |||
| } else { | |||
| $tip.css({visibility: 'visible', opacity: this.options.opacity}); | |||
| } | |||
| } | |||
| }, | |||
| hide: function() { | |||
| if (this.options.fade) { | |||
| this.tip().stop().fadeOut(function() { $(this).remove(); }); | |||
| } else { | |||
| this.tip().remove(); | |||
| } | |||
| }, | |||
| fixTitle: function() { | |||
| var $e = this.$element; | |||
| if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') { | |||
| $e.attr('original-title', $e.attr('title') || '').removeAttr('title'); | |||
| } | |||
| }, | |||
| getTitle: function() { | |||
| var title, $e = this.$element, o = this.options; | |||
| this.fixTitle(); | |||
| var title, o = this.options; | |||
| if (typeof o.title == 'string') { | |||
| title = $e.attr(o.title == 'title' ? 'original-title' : o.title); | |||
| } else if (typeof o.title == 'function') { | |||
| title = o.title.call($e[0]); | |||
| } | |||
| title = ('' + title).replace(/(^\s*|\s*$)/, ""); | |||
| return title || o.fallback; | |||
| }, | |||
| tip: function() { | |||
| if (!this.$tip) { | |||
| this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>'); | |||
| this.$tip.data('tipsy-pointee', this.$element[0]); | |||
| } | |||
| return this.$tip; | |||
| }, | |||
| validate: function() { | |||
| if (!this.$element[0].parentNode) { | |||
| this.hide(); | |||
| this.$element = null; | |||
| this.options = null; | |||
| } | |||
| }, | |||
| enable: function() { this.enabled = true; }, | |||
| disable: function() { this.enabled = false; }, | |||
| toggleEnabled: function() { this.enabled = !this.enabled; } | |||
| }; | |||
| $.fn.tipsy = function(options) { | |||
| if (options === true) { | |||
| return this.data('tipsy'); | |||
| } else if (typeof options == 'string') { | |||
| var tipsy = this.data('tipsy'); | |||
| if (tipsy) tipsy[options](); | |||
| return this; | |||
| } | |||
| options = $.extend({}, $.fn.tipsy.defaults, options); | |||
| function get(ele) { | |||
| var tipsy = $.data(ele, 'tipsy'); | |||
| if (!tipsy) { | |||
| tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); | |||
| $.data(ele, 'tipsy', tipsy); | |||
| } | |||
| return tipsy; | |||
| } | |||
| function enter() { | |||
| var tipsy = get(this); | |||
| tipsy.hoverState = 'in'; | |||
| if (options.delayIn == 0) { | |||
| tipsy.show(); | |||
| } else { | |||
| tipsy.fixTitle(); | |||
| setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn); | |||
| } | |||
| }; | |||
| function leave() { | |||
| var tipsy = get(this); | |||
| tipsy.hoverState = 'out'; | |||
| if (options.delayOut == 0) { | |||
| tipsy.hide(); | |||
| } else { | |||
| setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut); | |||
| } | |||
| }; | |||
| if (!options.live) this.each(function() { get(this); }); | |||
| if (options.trigger != 'manual') { | |||
| var binder = options.live ? 'live' : 'bind', | |||
| eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', | |||
| eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; | |||
| this[binder](eventIn, enter)[binder](eventOut, leave); | |||
| } | |||
| return this; | |||
| }; | |||
| $.fn.tipsy.defaults = { | |||
| className: null, | |||
| delayIn: 0, | |||
| delayOut: 0, | |||
| fade: false, | |||
| fallback: '', | |||
| gravity: 'n', | |||
| html: false, | |||
| live: false, | |||
| offset: 0, | |||
| opacity: 0.8, | |||
| title: 'title', | |||
| trigger: 'hover' | |||
| }; | |||
| $.fn.tipsy.revalidate = function() { | |||
| $('.tipsy').each(function() { | |||
| var pointee = $.data(this, 'tipsy-pointee'); | |||
| if (!pointee || !isElementInDOM(pointee)) { | |||
| $(this).remove(); | |||
| } | |||
| }); | |||
| }; | |||
| // Overwrite this method to provide options on a per-element basis. | |||
| // For example, you could store the gravity in a 'tipsy-gravity' attribute: | |||
| // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); | |||
| // (remember - do not modify 'options' in place!) | |||
| $.fn.tipsy.elementOptions = function(ele, options) { | |||
| return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; | |||
| }; | |||
| $.fn.tipsy.autoNS = function() { | |||
| return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; | |||
| }; | |||
| $.fn.tipsy.autoWE = function() { | |||
| return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; | |||
| }; | |||
| /** | |||
| * yields a closure of the supplied parameters, producing a function that takes | |||
| * no arguments and is suitable for use as an autogravity function like so: | |||
| * | |||
| * @param margin (int) - distance from the viewable region edge that an | |||
| * element should be before setting its tooltip's gravity to be away | |||
| * from that edge. | |||
| * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer | |||
| * if there are no viewable region edges effecting the tooltip's | |||
| * gravity. It will try to vary from this minimally, for example, | |||
| * if 'sw' is preferred and an element is near the right viewable | |||
| * region edge, but not the top edge, it will set the gravity for | |||
| * that element's tooltip to be 'se', preserving the southern | |||
| * component. | |||
| */ | |||
| $.fn.tipsy.autoBounds = function(margin, prefer) { | |||
| return function() { | |||
| var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)}, | |||
| boundTop = $(document).scrollTop() + margin, | |||
| boundLeft = $(document).scrollLeft() + margin, | |||
| $this = $(this); | |||
| if ($this.offset().top < boundTop) dir.ns = 'n'; | |||
| if ($this.offset().left < boundLeft) dir.ew = 'w'; | |||
| if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e'; | |||
| if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's'; | |||
| return dir.ns + (dir.ew ? dir.ew : ''); | |||
| } | |||
| }; | |||
| })(jQuery); | |||
| @@ -1,6 +1,6 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head{{if AppSubUrl}} data-suburl="{{AppSubUrl}}"{{end}}> | |||
| <head data-suburl="{{AppSubUrl}}"> | |||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | |||
| <meta name="author" content="Gogs - Go Git Service" /> | |||
| @@ -23,12 +23,14 @@ | |||
| <!-- Stylesheet --> | |||
| <link rel="stylesheet" href="{{AppSubUrl}}/ng/css/ui.css"> | |||
| <link rel="stylesheet" href="{{AppSubUrl}}/ng/css/gogs.css"> | |||
| <link rel="stylesheet" href="{{AppSubUrl}}/ng/css/tipsy.css"> | |||
| <link rel="stylesheet" href="{{AppSubUrl}}/ng/fonts/octicons.css"> | |||
| <link rel="stylesheet" href="{{AppSubUrl}}/css/github.min.css"> | |||
| <!-- JavaScript --> | |||
| <script src="{{AppSubUrl}}/ng/js/lib/tabs.js"></script> | |||
| <script src="{{AppSubUrl}}/ng/js/lib/lib.js"></script> | |||
| <script src="{{AppSubUrl}}/ng/js/lib/jquery.tipsy.js"></script> | |||
| <script src="{{AppSubUrl}}/ng/js/gogs.js"></script> | |||
| <title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title> | |||
| @@ -19,7 +19,7 @@ | |||
| <button class="btn btn-blue left left btn-left-radius" id="repo-clone-ssh" data-link="{{.CloneLink.SSH}}">SSH</button> | |||
| <button class="btn btn-gray left" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">HTTPS</button> | |||
| <input id="repo-clone-url" class="ipt ipt-disabled left" value="{{.CloneLink.SSH}}" readonly /> | |||
| <button id="repo-clone-copy" class="btn btn-black left btn-right-radius" data-copy-val="val" data-copy-from="#repo-clone-url">{{.i18n.Tr "repo.copy_link"}}</button> | |||
| <button id="repo-clone-copy" class="btn btn-black left btn-right-radius" data-copy-val="val" data-copy-from="#repo-clone-url" original-title="{{.i18n.Tr "repo.click_to_copy"}}" data-original-title="{{.i18n.Tr "repo.click_to_copy"}}" data-after-title="{{.i18n.Tr "repo.copied"}}">{{.i18n.Tr "repo.copy_link"}}</button> | |||
| <p class="text-center" id="repo-clone-help">{{.i18n.Tr "repo.clone_helper" | Str2html}}</p> | |||
| <hr/> | |||
| <div class="text-center" id="repo-clone-zip"> | |||