Merge branch 'feature/better.select' into feature/particles
This commit is contained in:
commit
616a489ae4
11 changed files with 462 additions and 62 deletions
|
@ -164,15 +164,16 @@ jQuery.browser = browser;
|
||||||
// START METAMAPS CODE
|
// START METAMAPS CODE
|
||||||
// Add code that makes tab and shift+tab scroll through metacodes
|
// Add code that makes tab and shift+tab scroll through metacodes
|
||||||
$('.new_topic').bind('keydown',this,function(event){
|
$('.new_topic').bind('keydown',this,function(event){
|
||||||
if (event.keyCode == 9) {
|
if (event.keyCode == 9 && event.shiftKey) {
|
||||||
if (event.shiftKey) {
|
$(container).show()
|
||||||
event.data.rotate(-1)
|
event.data.rotate(-1);
|
||||||
} else {
|
event.preventDefault();
|
||||||
event.data.rotate(1)
|
event.stopPropagation();
|
||||||
}
|
} else if (event.keyCode == 9) {
|
||||||
|
$(container).show()
|
||||||
|
event.data.rotate(1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
Metamaps.Create.newTopic.metacode = $(items[event.data.frontIndex].image).attr('data-id');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// END METAMAPS CODE
|
// END METAMAPS CODE
|
||||||
|
@ -181,14 +182,14 @@ jQuery.browser = browser;
|
||||||
if (options.mouseWheel)
|
if (options.mouseWheel)
|
||||||
{
|
{
|
||||||
// START METAMAPS CODE
|
// START METAMAPS CODE
|
||||||
$('body').bind('mousewheel',this,function(event, delta) {
|
/*$('body').bind('mousewheel',this,function(event, delta) {
|
||||||
if (Metamaps.Create.newTopic.beingCreated &&
|
if (Metamaps.Create.newTopic.beingCreated &&
|
||||||
!Metamaps.Create.isSwitchingSet &&
|
!Metamaps.Create.isSwitchingSet &&
|
||||||
!Metamaps.Create.newTopic.pinned) {
|
!Metamaps.Create.newTopic.pinned) {
|
||||||
event.data.rotate(delta);
|
event.data.rotate(delta);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
// END METAMAPS CODE
|
// END METAMAPS CODE
|
||||||
// ORIGINAL CODE
|
// ORIGINAL CODE
|
||||||
// $(container).bind('mousewheel',this,function(event, delta) {
|
// $(container).bind('mousewheel',this,function(event, delta) {
|
||||||
|
@ -255,8 +256,11 @@ jQuery.browser = browser;
|
||||||
this.showFrontText = function()
|
this.showFrontText = function()
|
||||||
{
|
{
|
||||||
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
||||||
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
// METAMAPS CODE
|
||||||
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
Metamaps.Create.newTopic.setMetacode($(items[this.frontIndex].image).attr('data-id'))
|
||||||
|
// NOT METAMAPS CODE
|
||||||
|
//$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
||||||
|
//$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.go = function()
|
this.go = function()
|
||||||
|
@ -270,6 +274,9 @@ jQuery.browser = browser;
|
||||||
{
|
{
|
||||||
clearTimeout(this.controlTimer);
|
clearTimeout(this.controlTimer);
|
||||||
this.controlTimer = 0;
|
this.controlTimer = 0;
|
||||||
|
// METAMAPS CODE
|
||||||
|
$(container).hide()
|
||||||
|
// END METAMAPS CODE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -390,7 +397,7 @@ jQuery.browser = browser;
|
||||||
}
|
}
|
||||||
// If all images have valid widths and heights, we can stop checking.
|
// If all images have valid widths and heights, we can stop checking.
|
||||||
clearInterval(this.tt);
|
clearInterval(this.tt);
|
||||||
this.showFrontText();
|
// METAMAPS COMMENT this.showFrontText();
|
||||||
this.autoRotate();
|
this.autoRotate();
|
||||||
this.updateAll();
|
this.updateAll();
|
||||||
|
|
||||||
|
|
|
@ -531,18 +531,48 @@ button.button.btn-no:hover {
|
||||||
left: -1000px;
|
left: -1000px;
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 340px;
|
|
||||||
margin: -40px 0 0 -35px;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selectedMetacode {
|
||||||
|
float: left;
|
||||||
|
background: #FFF;
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
padding: 5px 10px 5px 6px;
|
||||||
|
vertical-align: top;
|
||||||
|
border-right: 1px solid #DDD;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.selectedMetacode:hover, .selectedMetacode.isBeingSelected {
|
||||||
|
background: #EDEDED;
|
||||||
|
}
|
||||||
|
.selectedMetacode img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.selectedMetacode span {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.selectedMetacode .downArrow {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 8px 6px 0 6px;
|
||||||
|
border-color: #777 transparent transparent transparent;
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
#new_topic .twitter-typeahead {
|
#new_topic .twitter-typeahead {
|
||||||
position: absolute !important;
|
|
||||||
top: 45px;
|
|
||||||
left: 41px;
|
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
width: 256px;
|
width: 256px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
.new_topic #topic_name,
|
.new_topic #topic_name,
|
||||||
.new_topic .tt-hint {
|
.new_topic .tt-hint {
|
||||||
|
@ -552,7 +582,8 @@ button.button.btn-no:hover {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 10px 6px;
|
padding: 10px 6px;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 2px;
|
border-top-right-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
outline: none;
|
outline: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
|
@ -563,7 +594,7 @@ button.button.btn-no:hover {
|
||||||
color: #BDBDBD;
|
color: #BDBDBD;
|
||||||
}
|
}
|
||||||
.openMetacodeSwitcher {
|
.openMetacodeSwitcher {
|
||||||
display: block;
|
display: none;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
background-image: url(<%= asset_data_uri('metacodesettings_sprite.png') %>);
|
background-image: url(<%= asset_data_uri('metacodesettings_sprite.png') %>);
|
||||||
|
@ -583,8 +614,8 @@ button.button.btn-no:hover {
|
||||||
background-image: url(<%= asset_data_uri('pincarousel_sprite.png') %>);
|
background-image: url(<%= asset_data_uri('pincarousel_sprite.png') %>);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
top: 20px;
|
top: -20px;
|
||||||
right: 16px;
|
right: -16px;
|
||||||
}
|
}
|
||||||
.pinCarousel:hover {
|
.pinCarousel:hover {
|
||||||
background-position: 0 -16px;
|
background-position: 0 -16px;
|
||||||
|
@ -597,8 +628,14 @@ button.button.btn-no:hover {
|
||||||
}
|
}
|
||||||
#metacodeImg {
|
#metacodeImg {
|
||||||
height: 120px;
|
height: 120px;
|
||||||
|
width: 380px;
|
||||||
|
display: none;
|
||||||
|
position: absolute !important;
|
||||||
|
top: -30px;
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
#metacodeImgTitle {
|
#metacodeImgTitle {
|
||||||
|
display: none;
|
||||||
float: left;
|
float: left;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
72
app/assets/stylesheets/metacode-select.scss.erb
Normal file
72
app/assets/stylesheets/metacode-select.scss.erb
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#metacodeSelector {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metacodeSelect {
|
||||||
|
border-top: 1px solid #DDD;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.tabList {
|
||||||
|
float: left;
|
||||||
|
background: #FFF;
|
||||||
|
|
||||||
|
div {
|
||||||
|
border-right: 1px solid #DDD;
|
||||||
|
border-bottom: 1px solid #DDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.active {
|
||||||
|
border-right: none;
|
||||||
|
background: #EEE;
|
||||||
|
|
||||||
|
.metacodeFilterInput {
|
||||||
|
background: #EEE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.metacodeFilterInput {
|
||||||
|
width: 100px;
|
||||||
|
outline: none;
|
||||||
|
border: 0;
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 14px;
|
||||||
|
color: #424242;
|
||||||
|
font-family: 'din-medium', helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
padding: 8px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.metacodeList {
|
||||||
|
float:left;
|
||||||
|
list-style: none;
|
||||||
|
background: #FFF;
|
||||||
|
min-height: 107px;
|
||||||
|
min-width: 100px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover, &.keySelect {
|
||||||
|
background: #EEE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
before_action :require_user, only: [:edit, :update, :updatemetacodes]
|
before_action :require_user, only: [:edit, :update, :updatemetacodes, :update_metacode_focus]
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json
|
||||||
|
|
||||||
|
@ -92,6 +92,16 @@ class UsersController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# PUT /user/update_metacode_focus
|
||||||
|
def update_metacode_focus
|
||||||
|
@user = current_user
|
||||||
|
@user.settings.metacode_focus = params[:value]
|
||||||
|
@user.save
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render json: { success: "success" }}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def user_params
|
def user_params
|
||||||
|
|
|
@ -26,6 +26,10 @@ module ApplicationHelper
|
||||||
@metacodes.sort! { |m1, m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
|
@metacodes.sort! { |m1, m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def user_metacode
|
||||||
|
current_user.settings.metacode_focus ? Metacode.find(current_user.settings.metacode_focus.to_i) || user_metacodes()[0] : user_metacodes()[0]
|
||||||
|
end
|
||||||
|
|
||||||
def user_most_used_metacodes
|
def user_most_used_metacodes
|
||||||
@metacodes = current_user.most_used_metacodes.map { |id| Metacode.find(id) }
|
@metacodes = current_user.most_used_metacodes.map { |id| Metacode.find(id) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,6 +67,28 @@ class User < ApplicationRecord
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def recentMetacodes
|
||||||
|
array = []
|
||||||
|
self.topics.sort{|a,b| b.created_at <=> a.created_at }.each do |t|
|
||||||
|
if array.length < 5 and array.index(t.metacode_id) == nil
|
||||||
|
array.push(t.metacode_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
array
|
||||||
|
end
|
||||||
|
|
||||||
|
def mostUsedMetacodes
|
||||||
|
self.topics.to_a.reduce({}) { |memo, topic|
|
||||||
|
if memo[topic.metacode_id] == nil
|
||||||
|
memo[topic.metacode_id] = 1
|
||||||
|
else
|
||||||
|
memo[topic.metacode_id] = memo[topic.metacode_id] + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
memo
|
||||||
|
}.to_a.sort{ |a, b| b[1] <=> a[1] }.map{|i| i[0]}.slice(0, 5)
|
||||||
|
end
|
||||||
|
|
||||||
def all_accessible_maps
|
def all_accessible_maps
|
||||||
maps + shared_maps
|
maps + shared_maps
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class UserPreference
|
class UserPreference
|
||||||
attr_accessor :metacodes
|
attr_accessor :metacodes, :metacode_focus
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
array = []
|
array = []
|
||||||
|
@ -15,5 +15,6 @@ class UserPreference
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@metacodes = array
|
@metacodes = array
|
||||||
|
@metacode_focus = array[0]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,24 +11,36 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="metacodeImg">
|
<div id="metacodeImg">
|
||||||
|
<% @metacodes = [user_metacode()].concat(user_metacodes()).uniq %>
|
||||||
|
<% set = metacodeset() %>
|
||||||
<% @metacodes.each do |metacode| %>
|
<% @metacodes.each do |metacode| %>
|
||||||
<img class="cloudcarousel" width="40" height="40" src="<%= asset_path metacode.icon %>" alt="<%= metacode.name %>" title="<%= metacode.name %>" data-id="<%= metacode.id %>" />
|
<img class="cloudcarousel" width="40" height="40" src="<%= asset_path metacode.icon %>" alt="<%= metacode.name %>" title="<%= metacode.name %>" data-id="<%= metacode.id %>" />
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="selectedMetacode">
|
||||||
|
<img src="<%= asset_path user_metacode().icon %>" />
|
||||||
|
<span><%= user_metacode().name %></span>
|
||||||
|
<div class="downArrow"></div>
|
||||||
|
</div>
|
||||||
<%= form.text_field :name, :maxlength => 140, :placeholder => "title..." %>
|
<%= form.text_field :name, :maxlength => 140, :placeholder => "title..." %>
|
||||||
|
|
||||||
<div id="metacodeImgTitle"></div>
|
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
|
<div id="metacodeSelector"></div>
|
||||||
<script>
|
<div class="clearfloat"></div>
|
||||||
<% @metacodes.each do |metacode| %>
|
<script>
|
||||||
<% if !metacodeset() %>
|
<% @metacodes.each do |metacode| %>
|
||||||
|
<% if !set %>
|
||||||
Metamaps.Create.selectedMetacodes.push("<%= metacode.id %>");
|
Metamaps.Create.selectedMetacodes.push("<%= metacode.id %>");
|
||||||
Metamaps.Create.newSelectedMetacodes.push("<%= metacode.id %>");
|
Metamaps.Create.newSelectedMetacodes.push("<%= metacode.id %>");
|
||||||
Metamaps.Create.selectedMetacodeNames.push("<%= metacode.name %>");
|
Metamaps.Create.selectedMetacodeNames.push("<%= metacode.name %>");
|
||||||
Metamaps.Create.newSelectedMetacodeNames.push("<%= metacode.name %>");
|
Metamaps.Create.newSelectedMetacodeNames.push("<%= metacode.name %>");
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</script>
|
Metamaps.Create.newTopic.metacode = <%= user_metacode().id %>
|
||||||
|
<% current_user.recentMetacodes.each do |id| %>
|
||||||
|
Metamaps.Create.recentMetacodes.push(<%= id %>);
|
||||||
|
<% end %>
|
||||||
|
<% current_user.mostUsedMetacodes.each do |id| %>
|
||||||
|
Metamaps.Create.mostUsedMetacodes.push(<%= id %>);
|
||||||
|
<% end %>
|
||||||
|
</script>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -104,6 +104,7 @@ Metamaps::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
post 'user/updatemetacodes', to: 'users#updatemetacodes', as: :updatemetacodes
|
post 'user/updatemetacodes', to: 'users#updatemetacodes', as: :updatemetacodes
|
||||||
|
post 'user/update_metacode_focus', to: 'users#update_metacode_focus'
|
||||||
|
|
||||||
namespace :api, path: '/api', default: { format: :json } do
|
namespace :api, path: '/api', default: { format: :json } do
|
||||||
namespace :v2, path: '/v2' do
|
namespace :v2, path: '/v2' do
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
/* global $, Hogan, Bloodhound */
|
/* global Metamaps, $, Hogan, Bloodhound */
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
|
||||||
import DataModel from './DataModel'
|
import DataModel from './DataModel'
|
||||||
|
import MetacodeSelect from '../components/MetacodeSelect'
|
||||||
import Mouse from './Mouse'
|
import Mouse from './Mouse'
|
||||||
import Selected from './Selected'
|
import Selected from './Selected'
|
||||||
import Synapse from './Synapse'
|
import Synapse from './Synapse'
|
||||||
|
@ -17,7 +21,9 @@ const Create = {
|
||||||
newSelectedMetacodeNames: [],
|
newSelectedMetacodeNames: [],
|
||||||
selectedMetacodes: [],
|
selectedMetacodes: [],
|
||||||
newSelectedMetacodes: [],
|
newSelectedMetacodes: [],
|
||||||
init: function() {
|
recentMetacodes: [],
|
||||||
|
mostUsedMetacodes: [],
|
||||||
|
init: function () {
|
||||||
var self = Create
|
var self = Create
|
||||||
self.newTopic.init()
|
self.newTopic.init()
|
||||||
self.newSynapse.init()
|
self.newSynapse.init()
|
||||||
|
@ -76,7 +82,6 @@ const Create = {
|
||||||
}
|
}
|
||||||
metacodeModels.sort()
|
metacodeModels.sort()
|
||||||
|
|
||||||
$('#metacodeImg, #metacodeImgTitle').empty()
|
|
||||||
$('#metacodeImg').removeData('cloudcarousel')
|
$('#metacodeImg').removeData('cloudcarousel')
|
||||||
var newMetacodes = ''
|
var newMetacodes = ''
|
||||||
metacodeModels.each(function(metacode) {
|
metacodeModels.each(function(metacode) {
|
||||||
|
@ -84,13 +89,11 @@ const Create = {
|
||||||
})
|
})
|
||||||
|
|
||||||
$('#metacodeImg').empty().append(newMetacodes).CloudCarousel({
|
$('#metacodeImg').empty().append(newMetacodes).CloudCarousel({
|
||||||
titleBox: $('#metacodeImgTitle'),
|
|
||||||
yRadius: 40,
|
yRadius: 40,
|
||||||
xRadius: 190,
|
xRadius: 190,
|
||||||
xPos: 170,
|
xPos: 170,
|
||||||
yPos: 40,
|
yPos: 40,
|
||||||
speed: 0.3,
|
speed: 0.3,
|
||||||
mouseWheel: true,
|
|
||||||
bringToFront: true
|
bringToFront: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -140,17 +143,31 @@ const Create = {
|
||||||
$('#topic_name').focus()
|
$('#topic_name').focus()
|
||||||
},
|
},
|
||||||
newTopic: {
|
newTopic: {
|
||||||
init: function() {
|
init: function () {
|
||||||
$('#topic_name').keyup(function(e) {
|
const DOWN_ARROW = 40
|
||||||
const ESC = 27
|
const ESC = 27
|
||||||
|
|
||||||
|
$('#topic_name').keyup(function (e) {
|
||||||
|
|
||||||
|
Create.newTopic.name = $(this).val()
|
||||||
|
if (e.which == DOWN_ARROW && !Create.newTopic.name.length) {
|
||||||
|
Create.newTopic.openSelector()
|
||||||
|
}
|
||||||
|
|
||||||
if (e.keyCode === ESC) {
|
if (e.keyCode === ESC) {
|
||||||
Create.newTopic.hide()
|
Create.newTopic.hide()
|
||||||
} // if
|
} // if
|
||||||
|
|
||||||
Create.newTopic.name = $(this).val()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$('.selectedMetacode').click(function() {
|
||||||
|
if (Create.newTopic.metacodeSelectorOpen) {
|
||||||
|
Create.newTopic.hideSelector()
|
||||||
|
$('#topic_name').focus()
|
||||||
|
} else Create.newTopic.openSelector()
|
||||||
|
})
|
||||||
|
|
||||||
|
Create.newTopic.initSelector()
|
||||||
|
|
||||||
$('.pinCarousel').click(function() {
|
$('.pinCarousel').click(function() {
|
||||||
if (Create.newTopic.pinned) {
|
if (Create.newTopic.pinned) {
|
||||||
$('.pinCarousel').removeClass('isPinned')
|
$('.pinCarousel').removeClass('isPinned')
|
||||||
|
@ -201,16 +218,15 @@ const Create = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
$('#topic_name').click(function() { Create.newTopic.hideSelector() })
|
||||||
|
|
||||||
// initialize metacode spinner and then hide it
|
// initialize metacode spinner and then hide it
|
||||||
$('#metacodeImg').CloudCarousel({
|
$('#metacodeImg').CloudCarousel({
|
||||||
titleBox: $('#metacodeImgTitle'),
|
|
||||||
yRadius: 40,
|
yRadius: 40,
|
||||||
xRadius: 190,
|
xRadius: 190,
|
||||||
xPos: 170,
|
xPos: 170,
|
||||||
yPos: 40,
|
yPos: 40,
|
||||||
speed: 0.3,
|
speed: 0.3,
|
||||||
mouseWheel: true,
|
|
||||||
bringToFront: true
|
bringToFront: true
|
||||||
})
|
})
|
||||||
$('.new_topic').hide()
|
$('.new_topic').hide()
|
||||||
|
@ -219,13 +235,62 @@ const Create = {
|
||||||
name: null,
|
name: null,
|
||||||
newId: 1,
|
newId: 1,
|
||||||
beingCreated: false,
|
beingCreated: false,
|
||||||
|
metacodeSelectorOpen: false,
|
||||||
metacode: null,
|
metacode: null,
|
||||||
x: null,
|
x: null,
|
||||||
y: null,
|
y: null,
|
||||||
addSynapse: false,
|
addSynapse: false,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
open: function() {
|
initSelector: function () {
|
||||||
$('#new_topic').fadeIn('fast', function() {
|
ReactDOM.render(
|
||||||
|
React.createElement(MetacodeSelect, {
|
||||||
|
onClick: function (id) {
|
||||||
|
Create.newTopic.setMetacode(id)
|
||||||
|
Create.newTopic.hideSelector()
|
||||||
|
$('#topic_name').focus()
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
Create.newTopic.hideSelector()
|
||||||
|
$('#topic_name').focus()
|
||||||
|
},
|
||||||
|
metacodes: DataModel.Metacodes.models,
|
||||||
|
recent: Create.recentMetacodes,
|
||||||
|
mostUsed: Create.mostUsedMetacodes
|
||||||
|
}),
|
||||||
|
document.getElementById('metacodeSelector')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
openSelector: function () {
|
||||||
|
Create.newTopic.initSelector()
|
||||||
|
$('#metacodeSelector').show()
|
||||||
|
Create.newTopic.metacodeSelectorOpen = true
|
||||||
|
$('.metacodeFilterInput').focus()
|
||||||
|
$('.selectedMetacode').addClass('isBeingSelected')
|
||||||
|
},
|
||||||
|
hideSelector: function () {
|
||||||
|
ReactDOM.unmountComponentAtNode(document.getElementById('metacodeSelector'))
|
||||||
|
$('#metacodeSelector').hide()
|
||||||
|
Create.newTopic.metacodeSelectorOpen = false
|
||||||
|
$('.selectedMetacode').removeClass('isBeingSelected')
|
||||||
|
},
|
||||||
|
setMetacode: function (id) {
|
||||||
|
Create.newTopic.metacode = id
|
||||||
|
var metacode = DataModel.Metacodes.get(id)
|
||||||
|
$('.selectedMetacode img').attr('src', metacode.get('icon'))
|
||||||
|
$('.selectedMetacode span').html(metacode.get('name'))
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
url: '/user/update_metacode_focus',
|
||||||
|
data: { value: id },
|
||||||
|
success: function (data) {},
|
||||||
|
error: function () {
|
||||||
|
console.log('failed to save metacode focus')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
open: function () {
|
||||||
|
$('#new_topic').fadeIn('fast', function () {
|
||||||
$('#topic_name').focus()
|
$('#topic_name').focus()
|
||||||
})
|
})
|
||||||
Create.newTopic.beingCreated = true
|
Create.newTopic.beingCreated = true
|
||||||
|
@ -247,6 +312,7 @@ const Create = {
|
||||||
},
|
},
|
||||||
reset: function() {
|
reset: function() {
|
||||||
$('#topic_name').typeahead('val', '')
|
$('#topic_name').typeahead('val', '')
|
||||||
|
Create.newTopic.hideSelector()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
newSynapse: {
|
newSynapse: {
|
||||||
|
|
168
frontend/src/components/MetacodeSelect.js
Normal file
168
frontend/src/components/MetacodeSelect.js
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
/* global $ */
|
||||||
|
|
||||||
|
import React, { Component, PropTypes } from 'react'
|
||||||
|
|
||||||
|
const ENTER_KEY = 13
|
||||||
|
const LEFT_ARROW = 37
|
||||||
|
const UP_ARROW = 38
|
||||||
|
const RIGHT_ARROW = 39
|
||||||
|
const DOWN_ARROW = 40
|
||||||
|
|
||||||
|
const Metacode = (props) => {
|
||||||
|
const { m, onClick, underCursor } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li onClick={() => onClick(m.id) } className={ underCursor ? 'keySelect' : '' }>
|
||||||
|
<img src={ m.get('icon') } />
|
||||||
|
<span>{ m.get('name') }</span>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetacodeSelect extends Component {
|
||||||
|
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
filterText: '',
|
||||||
|
activeTab: 0,
|
||||||
|
selectingSection: true,
|
||||||
|
underCursor: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const self = this
|
||||||
|
setTimeout(function() {
|
||||||
|
$(document.body).on('keyup.metacodeSelect', self.handleKeyUp.bind(self))
|
||||||
|
}, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
$(document.body).off('.metacodeSelect')
|
||||||
|
}
|
||||||
|
|
||||||
|
changeFilterText (e) {
|
||||||
|
this.setState({ filterText: e.target.value, underCursor: 0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
changeDisplay (activeTab) {
|
||||||
|
this.setState({ activeTab, underCursor: 0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectMetacodes () {
|
||||||
|
const { metacodes, recent, mostUsed } = this.props
|
||||||
|
const { filterText, activeTab } = this.state
|
||||||
|
|
||||||
|
let selectMetacodes = []
|
||||||
|
if (activeTab == 0) { // search
|
||||||
|
selectMetacodes = filterText.length > 1 ? metacodes.filter(m => {
|
||||||
|
return m.get('name').toLowerCase().search(filterText.toLowerCase()) > -1
|
||||||
|
}) : []
|
||||||
|
} else if (activeTab == 1) { // recent
|
||||||
|
selectMetacodes = recent.map(id => {
|
||||||
|
return metacodes.find(m => m.id == id)
|
||||||
|
}).filter(m => m)
|
||||||
|
} else if (activeTab == 2) { // mostUsed
|
||||||
|
selectMetacodes = mostUsed.map(id => {
|
||||||
|
return metacodes.find(m => m.id == id)
|
||||||
|
}).filter(m => m)
|
||||||
|
}
|
||||||
|
return selectMetacodes
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyUp (e) {
|
||||||
|
const { close } = this.props
|
||||||
|
const { activeTab, underCursor, selectingSection } = this.state
|
||||||
|
const selectMetacodes = this.getSelectMetacodes()
|
||||||
|
let nextIndex
|
||||||
|
|
||||||
|
switch (e.which) {
|
||||||
|
case ENTER_KEY:
|
||||||
|
if (selectMetacodes.length && !selectingSection) this.resetAndClick(selectMetacodes[underCursor].id)
|
||||||
|
break
|
||||||
|
case UP_ARROW:
|
||||||
|
if (selectingSection && activeTab == 0) {
|
||||||
|
close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
else if (selectingSection) {
|
||||||
|
nextIndex = activeTab - 1
|
||||||
|
this.changeDisplay(nextIndex)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
nextIndex = underCursor == 0 ? selectMetacodes.length - 1 : underCursor - 1
|
||||||
|
this.setState({ underCursor: nextIndex })
|
||||||
|
break
|
||||||
|
case DOWN_ARROW:
|
||||||
|
if (selectingSection) {
|
||||||
|
nextIndex = activeTab == 2 ? 0 : activeTab + 1
|
||||||
|
this.changeDisplay(nextIndex)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
nextIndex = underCursor == selectMetacodes.length - 1 ? 0 : underCursor + 1
|
||||||
|
this.setState({ underCursor: nextIndex })
|
||||||
|
break
|
||||||
|
case RIGHT_ARROW:
|
||||||
|
if (selectingSection) this.setState({ selectingSection: false })
|
||||||
|
break
|
||||||
|
case LEFT_ARROW:
|
||||||
|
if (!selectingSection) this.setState({ selectingSection: true })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetAndClick (id) {
|
||||||
|
const { onClick } = this.props
|
||||||
|
this.setState({ filterText: '', underCursor: 0 })
|
||||||
|
this.changeDisplay(0)
|
||||||
|
onClick(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { onClick, close, recent, mostUsed } = this.props
|
||||||
|
const { filterText, activeTab, underCursor, selectingSection } = this.state
|
||||||
|
const selectMetacodes = this.getSelectMetacodes()
|
||||||
|
return <div className='metacodeSelect'>
|
||||||
|
<div className='tabList'>
|
||||||
|
<div className={ activeTab == 0 ? 'active' : '' }
|
||||||
|
onClick={() => { this.changeDisplay(0) }}>
|
||||||
|
<input type='text'
|
||||||
|
className='metacodeFilterInput'
|
||||||
|
placeholder='Search...'
|
||||||
|
ref='input'
|
||||||
|
value={ filterText }
|
||||||
|
onChange={ this.changeFilterText.bind(this) } />
|
||||||
|
</div>
|
||||||
|
<div className={ activeTab == 1 ? 'active' : '' }
|
||||||
|
onClick={() => { this.changeDisplay(1) }}>
|
||||||
|
<span>Recent</span>
|
||||||
|
</div>
|
||||||
|
<div className={ activeTab == 2 ? 'active' : '' }
|
||||||
|
onClick={() => { this.changeDisplay(2) }}>
|
||||||
|
<span>Most Used</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul className='metacodeList'>
|
||||||
|
{ selectMetacodes.map((m, index) => {
|
||||||
|
return <Metacode underCursor={!selectingSection && underCursor == index}
|
||||||
|
key={m.id}
|
||||||
|
m={m}
|
||||||
|
onClick={this.resetAndClick.bind(this)} />
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
<div className='clearfloat'></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MetacodeSelect.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
close: PropTypes.func.isRequired,
|
||||||
|
metacodes: PropTypes.array.isRequired,
|
||||||
|
recent: PropTypes.array.isRequired,
|
||||||
|
mostUsed: PropTypes.array.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MetacodeSelect
|
||||||
|
|
Loading…
Reference in a new issue