Treynolds_Qsearch - Version 0.0.1

Version Notes

This has been tested on Community 1.7.X and Enterprise 1.12.X. It is currently stable, without known bugs. It does not rely on any external libraries.

Download this release

Release Info

Developer Tim Reynolds
Extension Treynolds_Qsearch
Version 0.0.1
Comparing to
See all releases


Version 0.0.1

app/code/community/Treynolds/Qconfig/Block/Adminhtml/Qsearch.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Treynolds_Qconfig_Block_Adminhtml_Qsearch extends Mage_Adminhtml_Block_Template {
4
+ public function __construct() {
5
+ parent::__construct();
6
+ $this->setTemplate('treynolds/qconfig/qsearch.phtml');
7
+ }
8
+ }
app/code/community/Treynolds/Qconfig/Block/Adminhtml/System/Config/Edit.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Rewrite needed as the target block is anonymous, so can't be reliably referenced in layout */
3
+ class Treynolds_Qconfig_Block_Adminhtml_System_Config_Edit extends Mage_Adminhtml_Block_System_Config_Edit {
4
+
5
+ protected function _prepareLayout()
6
+ {
7
+ /* Inject our quick search block */
8
+ $this->setChild('qsearch', $this->getLayout()->createBlock('qconfig/adminhtml_qsearch'));
9
+ return parent::_prepareLayout();
10
+ }
11
+ public function getSaveButtonHtml()
12
+ {
13
+ return $this->getChildHtml('qsearch') . parent::getSaveButtonHtml();
14
+ }
15
+ }
app/code/community/Treynolds/Qconfig/Helper/Data.php ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Treynolds_Qconfig_Helper_Data extends Mage_Core_Helper_Abstract {
4
+ /**
5
+ * @param $qsearch string
6
+ * @param $sections Mage_Core_Model_Config_Element
7
+ * @param $configRoot Varien_Simplexml_Element
8
+ * @param $levelClause string
9
+ * @return array
10
+ */
11
+ protected function getNavRecords($qsearch, $sections, $configRoot, $levelClause){
12
+ $nav_ret = array();
13
+ $nodes = array_merge(
14
+ $sections->xpath('*[.//label[contains(translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "'.$qsearch.'") and ../'.$levelClause.'="1"]]')
15
+ ,$configRoot->xpath('*[./*/*[contains(translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "'. $qsearch.'")]]')
16
+
17
+ );
18
+
19
+ /* @var $node Mage_Core_Model_Config_Element */
20
+ foreach($nodes as $node){
21
+ $nav_ret[] = 'section/'. $node->getName(0);
22
+ }
23
+ return $nav_ret;
24
+ }
25
+ /**
26
+ * @param $qsearch string
27
+ * @param $sections Mage_Core_Model_Config_Element
28
+ * @param $configRoot Varien_Simplexml_Element
29
+ * @param $levelClause string
30
+ * @return array
31
+ */
32
+ protected function devGetNavRecords($qsearch, $sections, $configRoot, $levelClause){
33
+ $tmp_nav_counts = array();
34
+ $tmp_track = array();
35
+ $nodes = $configRoot->xpath('*/*/*[contains(translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "'. $qsearch.'")]');
36
+ foreach($nodes as $node){
37
+ $group = $node->xpath('..');
38
+ $section = $group[0]->xpath('..');
39
+ $section_name = $section[0]->getName();
40
+ $tmp_track[$section_name . '/' . $group[0]->getName() . '/' . $node->getName()] = 1;
41
+ if(isset($tmp_nav_counts[$section_name])){
42
+ $tmp_nav_counts[$section_name][0]++;
43
+ }
44
+ else {
45
+ $tmp_nav_counts[$section_name] = array(1,0);
46
+ }
47
+ }
48
+
49
+ $nodes = $sections->xpath('*/groups//label[contains(translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "'.$qsearch.'") and ../'.$levelClause.'="1"]');
50
+
51
+ foreach($nodes as $node){
52
+ $path = array();
53
+ $parent = $node->xpath('.');
54
+ $sanity = 0;
55
+ while($parent!==false && count($parent)>0 && $parent[0]->getName()!='sections' && $sanity++ < 10){
56
+ $path[] = $parent[0]->getName();
57
+ $parent = $parent[0]->xpath('./..');
58
+ }
59
+ $tmp_section = false;
60
+ $tmp_group = false;
61
+ $tmp_field = false;
62
+
63
+ /* The count is 4 when we matched a 'group' label */
64
+ if(count($path)==4){
65
+
66
+ $tmp_section = $path[3];
67
+ $tmp_group = true;//$path[3]. '/' . $path[1];
68
+
69
+ }
70
+ /* The count is 6 when we match a 'field' label */
71
+ else if(count($path)==6) {
72
+ $tmp_section = $path[5];
73
+ $tmp_field = $path[5] . '/' . $path[3] . '/' . $path[1];
74
+ }
75
+
76
+
77
+ if($tmp_section!==false){
78
+ if($tmp_group){
79
+ if(isset($tmp_nav_counts[$tmp_section])){
80
+ $tmp_nav_counts[$tmp_section][1]++;
81
+ }
82
+ else {
83
+ $tmp_nav_counts[$tmp_section]= array(0,1);
84
+ }
85
+ }
86
+
87
+ if($tmp_field && !isset($tmp_track[$tmp_field])){
88
+ $tmp_track[$tmp_field] = 1;
89
+ if(isset($tmp_nav_counts[$tmp_section])){
90
+ $tmp_nav_counts[$tmp_section][0]++;
91
+
92
+ }
93
+ else {
94
+ $tmp_nav_counts[$tmp_section]= array(1,0);
95
+
96
+ }
97
+ }
98
+ }
99
+
100
+ }
101
+ $nav_ret = array();
102
+ foreach($tmp_nav_counts as $section=>$counts){
103
+ $nav_ret[] = array('section/'.$section, $counts[0], $counts[1]);
104
+ }
105
+
106
+
107
+ return $nav_ret;
108
+ }
109
+
110
+ /**
111
+ * @param $qsearch string
112
+ * @param $current string
113
+ * @param $sections Mage_Core_Model_Config_Element
114
+ * @param $levelClause string
115
+ * @return array
116
+ */
117
+ protected function getGroupAndFieldRecordsByLabel($qsearch, $current, $sections, $levelClause){
118
+ $group_ret = array();
119
+ $field_ret = array();
120
+ $nodes = $sections->xpath($current . '/groups//label[contains(translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "'.$qsearch.'") and ../'.$levelClause.'="1"]');
121
+
122
+ foreach($nodes as $node){
123
+ $path = array();
124
+ $parent = $node->xpath('.');
125
+ $sanity = 0;
126
+ while($parent[0]->getName()!=$current && $sanity++ < 10){
127
+ $path[] = $parent[0]->getName();
128
+ $parent = $parent[0]->xpath('./..');
129
+ }
130
+ $path[] = $current;
131
+ /* The count is 4 when we matched a 'group' label */
132
+ if(count($path)==4){
133
+ $group_ret[] = $path[3]. '_' . $path[1];
134
+ }
135
+ /* The count is 6 when we match a 'field' label */
136
+ else if(count($path)==6) {
137
+ $group_ret[] = $path[5]. '_' . $path[3];
138
+ $field_ret[] ='row_' . $path[5] . '_' . $path[3] . '_' . $path[1];
139
+ }
140
+
141
+ }
142
+
143
+ return array($group_ret, $field_ret);
144
+ }
145
+
146
+ /**
147
+ * @param $qsearch string
148
+ * @param $current string
149
+ * @param $configRoot Varien_Simplexml_Element
150
+ * @return array
151
+ */
152
+ protected function getGroupAndFieldRecordsByValue($qsearch, $current, $configRoot){
153
+ $group_ret = array();
154
+ $field_ret = array();
155
+
156
+ $nodes = $configRoot->xpath($current . '//*[contains(translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "'. $qsearch.'")]');
157
+ foreach($nodes as $node){
158
+ $path = array();
159
+
160
+ $parent = $node->xpath('.');
161
+ $sanity = 0;
162
+ while($parent[0]->getName()!=$current && $sanity++ < 10){
163
+ $path[] = $parent[0]->getName();
164
+ $parent = $parent[0]->xpath('./..');
165
+ }
166
+ $path[] = $current;
167
+ if(count($path)==3){
168
+ $field_ret[] = 'row_' . $path[2] . '_' . $path[1] . '_' . $path[0];
169
+ $group_ret[] = $path[2] . '_' . $path[1];
170
+ }
171
+
172
+ }
173
+
174
+
175
+ return array($group_ret, $field_ret);
176
+ }
177
+
178
+ /**
179
+ * @param $qsearch string Query String
180
+ * @param $current string The current section of config you are viewing
181
+ * @param $website string The current website you are under. Can be null or empty string
182
+ * @param $store string The store view you are under. Can be null or empty string
183
+ * @return array with keys (nav, group, field), each of which is an array of strings
184
+ */
185
+ public function getQuickSearchResults($qsearch, $current, $website, $store){
186
+ if(is_null($current)){
187
+ $current = 'general';//This is currently not needed. Parameter gets set in adminhtml/system_config_tabs:122
188
+ }
189
+
190
+ $qsearch = trim(strtolower($qsearch));
191
+ if(strlen($qsearch)==0){
192
+ return array('nav'=>array(),'group'=>array(), 'field'=>array());
193
+ }
194
+ $qsearch = preg_replace('/("|\[|\]|\(|\))/','',$qsearch);
195
+ $levelClause = $this->getLevelClause($website, $store);
196
+ /* @var $formBlock Mage_Adminhtml_Block_System_Config_Form */
197
+ $formBlock = Mage::app()->getLayout()->createBlock('adminhtml/system_config_form');
198
+ /* @var $sections Varien_Simplexml_Element */
199
+ $configRoot = $formBlock->getConfigRoot();
200
+ /* @var $sections Mage_Core_Model_Config_Element */
201
+ $sections = $this->getSections($current, $website, $store);
202
+ /**
203
+ * First, get the top-level nodes for the left-hand nav.
204
+ */
205
+ $nav_ret = $this->getNavRecords($qsearch, $sections, $configRoot, $levelClause);
206
+
207
+
208
+ /**
209
+ * For finding the elements on your page we have to do things a little different
210
+ * We can't combine the xpath because we are grabbing the lowest level nodes
211
+ * and since the xml structure of the Config differs from the structure of the
212
+ * config display xml the parsing is slightly different.
213
+ * Essentially, in the config display xml there is a max depth and there are
214
+ * filler tags (groups, fields). In the actual config xml there aren't fillers
215
+ * and the depth can be more variable.
216
+ *
217
+ * This results in an array with duplicates, but that doesn't have much effect
218
+ * on the front-end.
219
+ */
220
+ /* Config display xml for the page you are on */
221
+ $by_label = $this->getGroupAndFieldRecordsByLabel($qsearch, $current, $sections, $levelClause);
222
+ /* Next we get the actual config xml for the page you are on */
223
+ $by_value = $this->getGroupAndFieldRecordsByValue($qsearch, $current, $configRoot);
224
+ /* Finally, we handle edge cases */
225
+ //TODO: Figure out how to handle edge cases
226
+
227
+
228
+ $group_ret = array_merge($by_value[0], $by_label[0]);
229
+ $field_ret = array_merge($by_value[1], $by_label[1]);
230
+ return array('nav'=>$nav_ret, 'group'=>$group_ret, 'field'=>$field_ret);
231
+ }
232
+
233
+ /**
234
+ * @param $current string
235
+ * @param $website string
236
+ * @param $store string
237
+ * @return Mage_Core_Model_Config_Element
238
+ */
239
+ protected function getSections($current, $website, $store){
240
+ /* @var $cache Mage_Core_Model_Cache */
241
+ $cache = Mage::getSingleton('core/cache');
242
+ $cache_id = 'treynolds_qcache_' . $website . '_' . $store;
243
+ /* Check the cache */
244
+ /* @var $sections Mage_Core_Model_Config_Element */
245
+ $sections = null;
246
+ /* @var $sections_xml string */
247
+ $sections_xml = $cache->load($cache_id);
248
+ if(!$sections_xml){
249
+ /* @var $configFields Mage_Adminhtml_Model_Config */
250
+ $configFields = Mage::getSingleton('adminhtml/config');
251
+ $sections = $configFields->getSections($current);
252
+ $cache->save($sections->asXml(), $cache_id, array(Mage_Core_Model_Config::CACHE_TAG));
253
+ }
254
+ else {
255
+ $sections = new Mage_Core_Model_Config_Element($sections_xml);
256
+ }
257
+
258
+ return $sections;
259
+ }
260
+
261
+ /**
262
+ * @return array where the key is a string to match qsearch
263
+ * and the value is an array of xpath clauses
264
+ */
265
+ protected function getNavEdgeCases(){
266
+ return array('yes'=>1, 'no'=>0, 'enabled'=>1, 'disabled'=>0);
267
+ }
268
+
269
+ /**
270
+ * Need to check the "show_in_X" tags in system.xml files
271
+ * @param $website string
272
+ * @param $store string
273
+ * @return string
274
+ */
275
+ protected function getLevelClause($website, $store){
276
+ if(!is_null($store) && strlen($store)>0){
277
+ return 'show_in_store';
278
+ }
279
+ if(!is_null($website) && strlen($website)>0){
280
+ return 'show_in_website';
281
+ }
282
+ return 'show_in_default';
283
+ }
284
+ }
app/code/community/Treynolds/Qconfig/controllers/Adminhtml/QconfigController.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Treynolds_Qconfig_Adminhtml_QconfigController extends Mage_Adminhtml_Controller_Action {
4
+ public function searchAction(){
5
+ $_qsearch = $this->getRequest()->getParam('qsearch');
6
+ $_website = $this->getRequest()->getParam('website');
7
+ $_store = $this->getRequest()->getParam('store');
8
+ $_section = $this->getRequest()->getParam('section');
9
+ header('Content-Type: application/json');
10
+ echo Mage::helper('core')->jsonEncode(Mage::helper('qconfig')->getQuickSearchResults($_qsearch, $_section, $_website, $_store));
11
+ exit();
12
+ }
13
+
14
+
15
+
16
+ }
app/code/community/Treynolds/Qconfig/etc/config.xml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Treynolds_Qconfig>
5
+ <version>0.0.1</version>
6
+ </Treynolds_Qconfig>
7
+ </modules>
8
+ <global>
9
+ <helpers>
10
+ <qconfig>
11
+ <class>Treynolds_Qconfig_Helper</class>
12
+ </qconfig>
13
+ </helpers>
14
+ <blocks>
15
+ <qconfig>
16
+ <class>Treynolds_Qconfig_Block</class>
17
+ </qconfig>
18
+ <adminhtml>
19
+ <rewrite>
20
+ <system_config_edit>Treynolds_Qconfig_Block_Adminhtml_System_Config_Edit</system_config_edit>
21
+ </rewrite>
22
+ </adminhtml>
23
+ </blocks>
24
+ </global>
25
+ <adminhtml>
26
+ <layout>
27
+ <updates>
28
+ <qconfig>
29
+ <file>treynolds/qconfig.xml</file>
30
+ </qconfig>
31
+ </updates>
32
+ </layout>
33
+ </adminhtml>
34
+ <admin>
35
+ <routers>
36
+ <adminhtml>
37
+ <args>
38
+ <modules>
39
+ <Treynolds_Qconfig before="Mage_Adminhtml">Treynolds_Qconfig_Adminhtml</Treynolds_Qconfig>
40
+ </modules>
41
+ </args>
42
+ </adminhtml>
43
+ </routers>
44
+ </admin>
45
+ </config>
app/design/adminhtml/default/default/layout/treynolds/qconfig.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <adminhtml_system_config_index>
4
+ <reference name="head">
5
+ <action method="addCss">
6
+ <file>treynolds/qconfig.css</file>
7
+ </action>
8
+ <action method="addJs">
9
+ <file>treynolds/qconfig.js</file>
10
+ </action>
11
+ </reference>
12
+ </adminhtml_system_config_index>
13
+ <adminhtml_system_config_edit>
14
+ <reference name="head">
15
+ <action method="addCss">
16
+ <file>treynolds/qconfig.css</file>
17
+ </action>
18
+ <action method="addJs">
19
+ <file>treynolds/qconfig.js</file>
20
+ </action>
21
+ </reference>
22
+ </adminhtml_system_config_edit>
23
+ </layout>
app/design/adminhtml/default/default/template/treynolds/qconfig/qsearch.phtml ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $_qsearch = $this->getRequest()->getParam('qsearch');
3
+ $_website = $this->getRequest()->getParam('website');
4
+ $_store = $this->getRequest()->getParam('store');
5
+ $_section = $this->getRequest()->getParam('section');
6
+ ?>
7
+ <label for="treynolds_qconfig_box" >
8
+ <?php echo $this->__('Quick Search'); ?>
9
+ </label>
10
+ <div class="treynolds_qconfig_box_wrap">
11
+ <input type="text" onkeyup="qconfig_onkeyup(event);" value="<?php echo $this->escapeHtml($this->getRequest()->getParam('qsearch')); ?>" id="treynolds_qconfig_box" class="treynolds_qconfig_box">
12
+ <div class="treynolds_qconfig_no_results">
13
+ <?php echo $this->__('No Matches'); ?>
14
+
15
+ </div>
16
+ </div>
17
+
18
+ <a class="treynolds_qconfig_clear" href="#" onclick="qconfig_clear(); return false;">
19
+ <div class="treynolds_qconfig_loading"></div>
20
+ &nbsp;
21
+ </a>
22
+ <script type="text/javascript">
23
+ var qconfig;
24
+ function qconfig_onkeyup(event){
25
+ //27 is the key code for the ESC key.
26
+ if(event.which == 27 || event.keyCode == 27){
27
+ qconfig_clear();
28
+ }
29
+ else {
30
+ var target = (event.currentTarget) ? event.currentTarget : event.srcElement ;
31
+ qconfig.onkeyup(target);
32
+ }
33
+ }
34
+ function qconfig_clear(){
35
+ qconfig.onescape();
36
+ }
37
+ document.observe('dom:loaded',
38
+ function(){
39
+ qconfig = new Qconfig(
40
+ '<?php echo $this->escapeHtml($this->getUrl('adminhtml/qconfig/search')); ?>',
41
+ '<?php echo $this->escapeHtml($_website); ?>',
42
+ '<?php echo $this->escapeHtml($_store); ?>',
43
+ '<?php echo $this->escapeHtml($_section); ?>'
44
+ );
45
+
46
+ $$('#system_config_tabs dd a').each(function(link){
47
+ $(link).observe('click', function(event){
48
+ window.location = link.readAttribute('href').replace(/(\?.*$)/,'')+'?qsearch='+$('treynolds_qconfig_box').getValue();
49
+ Event.stop(event);
50
+ });
51
+
52
+ });
53
+ <?php if(Mage::app()->getRequest()->getParam('qsearch')): ?>
54
+ qconfig.handle_success(<?php echo Mage::helper('core')->jsonEncode(Mage::helper('qconfig')->getQuickSearchResults($_qsearch, $_section, $_website, $_store));?>, null, null);
55
+ <?php endif; ?>
56
+ }
57
+ );
58
+ </script>
app/etc/modules/Treynolds_Qconfig.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Treynolds_Qconfig>
5
+ <codePool>community</codePool>
6
+ <active>true</active>
7
+ </Treynolds_Qconfig>
8
+ </modules>
9
+ </config>
js/treynolds/qconfig.js ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Qconfig = Class.create();
2
+ Qconfig.prototype = {
3
+ initialize:function (url, website, store, section) {
4
+ this.url = url;
5
+ this.website = website;
6
+ this.store = store;
7
+ this.section = section;
8
+ this.request = null;
9
+ this.timeout = null;
10
+ this.timeout_delay = 400;
11
+ },
12
+ onkeyup:function (box) {
13
+ $$('.treynolds_qconfig_box').each(function (sync_box) {
14
+ if (sync_box != box) {
15
+ sync_box.setValue(box.getValue());
16
+ }
17
+
18
+ });
19
+ if (this.timeout != null) {
20
+ clearTimeout(this.timeout);
21
+ }
22
+ this.timeout = setTimeout(this.ontimeout.bind(this), this.timeout_delay);
23
+ },
24
+ ontimeout:function () {
25
+ this.timeout = null;
26
+
27
+ if (this.request != null) {
28
+ this.request.abort();
29
+ }
30
+ var query_string = $('treynolds_qconfig_box').getValue().strip();
31
+ if (query_string.length == 0) {
32
+ this.clear_searching();
33
+ return;
34
+ }
35
+ $$('.treynolds_qconfig_loading').each(
36
+ function(elm){
37
+ elm.addClassName('treynolds_loading');
38
+ }
39
+ );
40
+ new Ajax.Request(this.url, {
41
+ method:'get',
42
+ loaderArea:false,
43
+ parameters:{
44
+ qsearch:query_string,
45
+ section:this.section,
46
+ website:this.website,
47
+ store:this.store
48
+ },
49
+ onSuccess:this.onsuccess.bind(this)
50
+
51
+ }
52
+ );
53
+ },
54
+ onsuccess:function (transport) {
55
+ this.handle_success(transport.responseJSON);
56
+ },
57
+ handle_success:function (data) {
58
+ this.clear_searching();
59
+ $$('#system_config_tabs, .entry-edit').each(
60
+ function (elm) {
61
+ elm.addClassName('treynolds_searching');
62
+ }
63
+ );
64
+
65
+ if(data.nav.length == 0 && data.group.length == 0 && data.field.length == 0){
66
+ this.handle_no_results()
67
+ return;
68
+ }
69
+
70
+ for (var i = 0; i < data.nav.length; i++) {
71
+ $$('#system_config_tabs a[href*="' + data.nav[i] + '"]').each(
72
+ function (elm) {
73
+ elm.up().addClassName('treynolds_active');
74
+ }
75
+ );
76
+ }
77
+ var tmp = null;
78
+ if (data.group.length > 0) {
79
+ for (i = 0; i < data.group.length; i++) {
80
+ tmp = $(data.group[i] + '-head');
81
+ if (tmp != null) {
82
+ tmp.up().addClassName('treynolds_active');
83
+ }
84
+ }
85
+ }
86
+ if (data.field.length > 0) {
87
+ for (i = 0; i < data.field.length; i++) {
88
+ tmp = $(data.field[i]);
89
+ if (tmp != null) {
90
+ tmp.addClassName('treynolds_active');
91
+ }
92
+ }
93
+ }
94
+
95
+ $$('.treynolds_active').each(function (t) {
96
+
97
+ if (t.previous() != null && t.previous().hasClassName('treynolds_active')) {
98
+ t.addClassName('treynolds_bottom');
99
+ }
100
+ if (t.next() != null && t.next().hasClassName('treynolds_active')) {
101
+ t.addClassName('treynolds_top');
102
+ }
103
+ if(t.hasClassName('entry-edit-head')){
104
+ var count = t.up().select('.form-list .treynolds_active').length ;
105
+ var span = new Element('span', {'class':'treynolds_qconfig_field_count'}).update(count + ' Field'+(count==1?' Matches':'s Match'));
106
+ t.select('a')[0].insert(span);
107
+ }
108
+ });
109
+ },
110
+ onescape:function(){
111
+ //Don't want a request coming back after we clear.
112
+ if(this.timeout != null){
113
+ clearTimeout(this.timeout);
114
+ this.timeout = null;
115
+ }
116
+ $$('.treynolds_qconfig_box').each(function(box){
117
+ box.setValue('');
118
+ });
119
+ this.clear_searching();
120
+ },
121
+ handle_no_results:function(){
122
+ $$('.treynolds_qconfig_box_wrap').each(function(noresults){
123
+ noresults.addClassName('no_results');
124
+ });
125
+ },
126
+ clear_searching:function () {
127
+ $$('.treynolds_loading').each(
128
+ function (elm){
129
+ elm.removeClassName('treynolds_loading');
130
+ }
131
+ );
132
+ $$('.no_results').each(
133
+ function (elm){
134
+ elm.removeClassName('no_results');
135
+ }
136
+ );
137
+ $$('.treynolds_active').each(
138
+ function (elm) {
139
+ elm.removeClassName('treynolds_active');
140
+ elm.removeClassName('treynolds_top');
141
+ elm.removeClassName('treynolds_bottom');
142
+ }
143
+ );
144
+ $$('.treynolds_searching').each(
145
+ function (elm) {
146
+ elm.removeClassName('treynolds_searching');
147
+ }
148
+ );
149
+ $$('.treynolds_qconfig_field_count, b.treynolds_nav_count').each(
150
+ function(elm){
151
+ elm.remove();
152
+ }
153
+ );
154
+ }
155
+ };
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Treynolds_Qsearch</name>
4
+ <version>0.0.1</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Adds Quick Search functionality to the Admin -&gt; System -&gt; Configuration page.</summary>
10
+ <description>A simple but effective module to make working in the System -&gt; Configuration area of the Magento Admin easier for my clients. With qsearch you get a text box that will search the labels and values of fields for any that match your input. Areas that don't match will be shaded out, allowing you to quickly and accurately navigate the configuration area. </description>
11
+ <notes>This has been tested on Community 1.7.X and Enterprise 1.12.X. It is currently stable, without known bugs. It does not rely on any external libraries. </notes>
12
+ <authors><author><name>Tim Reynolds</name><user>timreynolds</user><email>reynolds.timj@gmail.com</email></author></authors>
13
+ <date>2012-10-26</date>
14
+ <time>18:59:11</time>
15
+ <contents><target name="magecommunity"><dir name="Treynolds"><dir name="Qconfig"><dir name="Block"><dir name="Adminhtml"><file name="Qsearch.php" hash="4d999525f1192554818c0502fc375dd0"/><dir name="System"><dir name="Config"><file name="Edit.php" hash="23e969d321efc6d568b9a9a5d467c5a3"/></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="2171565f47e31df689f582306b9023aa"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="QconfigController.php" hash="67bcd4fe6344bd9276bd5ce510eee444"/></dir></dir><dir name="etc"><file name="config.xml" hash="4d308050681f197ed31282bac2e0b0a6"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="treynolds"><file name="qconfig.xml" hash="0133fbbbb066d8ef762df43bdde98dca"/></dir></dir><dir name="template"><dir name="treynolds"><dir name="qconfig"><file name="qsearch.phtml" hash="54256feeb5cd421f658e9210633fca3f"/></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="treynolds"><file name="ajax-loader.gif" hash="394bafc3cc4dfb3a0ee48c1f54669539"/><file name="qconfig.css" hash="6ad9d4a0ed3807f353fdbf9392fd5ed0"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Treynolds_Qconfig.xml" hash="388ba20b88932a6b99967f80fda43505"/></dir></target><target name="mage"><dir name="js"><dir name="treynolds"><file name="qconfig.js" hash="301f9abaedbe747b1069199e08625692"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>5.3.0</max></php></required></dependencies>
18
+ </package>
skin/adminhtml/base/default/treynolds/ajax-loader.gif ADDED
Binary file
skin/adminhtml/base/default/treynolds/qconfig.css ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .treynolds_qconfig_clear, .treynolds_qconfig_clear:hover {
2
+ display: inline-block;
3
+ position: relative;
4
+ width: 20px;
5
+ height: 20px;
6
+
7
+ margin-left: -23px;
8
+ background: url(../../../default/default/images/cancel_icon.gif) center center no-repeat;
9
+ text-decoration: none;
10
+ }
11
+ .treynolds_qconfig_loading {
12
+ background: url(ajax-loader.gif) top left no-repeat;
13
+ display: none;
14
+ position: absolute;
15
+ width: 32px;
16
+ height: 32px;
17
+ top: -6px;
18
+ left: -6px;
19
+ }
20
+ .treynolds_qconfig_loading.treynolds_loading {
21
+ display: block;
22
+ }
23
+ .treynolds_qconfig_box_wrap {
24
+ display: inline-block;
25
+ /* IE7 Fix */
26
+ zoom: 1;
27
+ *display: inline;
28
+ position: relative;
29
+ }
30
+ .treynolds_qconfig_box_wrap .treynolds_qconfig_no_results {
31
+ /*background-color: #6F8992;*/
32
+ background: url(../../../default/default/images/nav1_active.gif) center center no-repeat;
33
+ color: #fff;
34
+ font-weight: bold;
35
+ text-align: center;
36
+ position: absolute;
37
+ top: 100%;
38
+ left: 0;
39
+ right: 0;
40
+ border-bottom-left-radius: 6px;
41
+ border-bottom-right-radius: 6px;
42
+ height: 0;
43
+ opacity: 0;
44
+ /* IE8 Fix */
45
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
46
+ /* IE7 Fix */
47
+ filter: alpha(opacity=0);
48
+ -webkit-transition: all 0.5s ease;
49
+ -moz-transition: all 0.5s ease;
50
+ -ms-transition: all 0.5s ease;
51
+ -o-transition: all 0.5s ease;
52
+ transition: all 0.5s ease;
53
+
54
+ }
55
+ .treynolds_qconfig_box_wrap.no_results .treynolds_qconfig_no_results{
56
+ opacity: 1.0;
57
+ /* IE8 Fix */
58
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
59
+ /* IE7 Fix */
60
+ filter: alpha(opacity=100);
61
+ height: 20px;
62
+ -webkit-transition: all 0.5s ease;
63
+ -moz-transition: all 0.5s ease;
64
+ -ms-transition: all 0.5s ease;
65
+ -o-transition: all 0.5s ease;
66
+ transition: all 0.5s ease;
67
+ }
68
+
69
+ .treynolds_qconfig_field_count {
70
+ float: right;
71
+ text-align: center;
72
+ padding: 0 7px;
73
+ margin-right: 25px;
74
+ background: url(../../../default/default/images/nav1_active.gif) center center no-repeat;
75
+ border-radius: 8px;
76
+
77
+ }
78
+
79
+ #system_config_tabs.treynolds_searching dd.treynolds_active span b {
80
+ float: right;
81
+ color: #fff;
82
+ background: url(../../../default/default/images/nav1_active.gif) center center no-repeat;
83
+ padding: 0 4px;
84
+ border-radius: 8px;
85
+
86
+ }
87
+
88
+ #system_config_tabs.treynolds_searching dd a ,
89
+ #system_config_tabs.treynolds_searching dd a:hover {
90
+ background: #929292 none;
91
+
92
+ }
93
+ #system_config_tabs.treynolds_searching dd a span ,
94
+ #system_config_tabs.treynolds_searching dd a:hover span {
95
+ cursor: no-drop;
96
+ background: #929292 none;
97
+ }
98
+ #system_config_tabs.treynolds_searching dd a.active span ,
99
+ #system_config_tabs.treynolds_searching dd a.active:hover span {
100
+ cursor: no-drop;
101
+ background: #929292 none;
102
+ }
103
+ #system_config_tabs.treynolds_searching dd a.paypal-section:hover,
104
+ #system_config_tabs.treynolds_searching dd a.paypal-section {
105
+ padding: 0;
106
+ }
107
+ #system_config_tabs.treynolds_searching dd a.paypal-section:hover span ,
108
+ #system_config_tabs.treynolds_searching dd a.paypal-section span {
109
+ height: auto;
110
+ overflow: visible;
111
+ width: auto;
112
+ padding:.3em 0.5em .28em 1.5em;
113
+ }
114
+ #system_config_tabs.treynolds_searching {
115
+ background: #929292 none !important;
116
+ }
117
+
118
+ #system_config_tabs.treynolds_searching .treynolds_active span {
119
+ cursor: pointer !important;
120
+
121
+ background:url(../../../default/default/images/tabs_link_bg.gif) repeat-y 100% #E7EFEF !important;
122
+ font-weight: bold;
123
+ border-radius: 12px;
124
+ }
125
+ #system_config_tabs.treynolds_searching .treynolds_active a.active {
126
+ border-bottom: 0;
127
+ }
128
+ #system_config_tabs.treynolds_searching .treynolds_active a.active span {
129
+ background-color: #fff !important;
130
+ }
131
+ #system_config_tabs.treynolds_searching .treynolds_active a:hover span {
132
+ background-color: #d8e6e6 !important;
133
+ }
134
+
135
+ #system_config_tabs.treynolds_searching .treynolds_active.treynolds_top span {
136
+ border-bottom-right-radius: 0 !important;
137
+ border-bottom-left-radius: 0 !important;
138
+ }
139
+ #system_config_tabs.treynolds_searching .treynolds_active.treynolds_bottom span {
140
+ border-top-right-radius: 0 !important;
141
+ border-top-left-radius: 0 !important;
142
+ }
143
+
144
+ .entry-edit.treynolds_searching .entry-edit-head ,
145
+ .entry-edit.treynolds_searching .entry-edit-head a {
146
+ background-color: #596f77;
147
+ color: #cbcbcb;
148
+ cursor: no-drop;
149
+ font-weight: normal;
150
+ }
151
+ .entry-edit.treynolds_searching .entry-edit-head.treynolds_active {
152
+ /*background-color: #7c98a2;*/
153
+ padding: 2px 10px 2px 5px;
154
+ cursor: pointer !important;
155
+ color: #fff;
156
+ }
157
+ .entry-edit.treynolds_searching .entry-edit-head.treynolds_active a{
158
+ border-radius: 9px;
159
+ padding: 0 0 0 5px;
160
+ background-color: #7c98a2;
161
+ font-weight: bold;
162
+ color: #fff;
163
+ cursor: pointer !important;
164
+ }
165
+ .entry-edit.treynolds_searching fieldset ,
166
+ .entry-edit.treynolds_searching input ,
167
+ .entry-edit.treynolds_searching textarea ,
168
+ .entry-edit.treynolds_searching select {
169
+ background-color: #a7a7a7;
170
+ }
171
+ .entry-edit.treynolds_searching tr {
172
+
173
+ }
174
+
175
+ .entry-edit.treynolds_searching tr.treynolds_active td {
176
+ background-color: #fafafa !important;
177
+
178
+ }
179
+ .entry-edit.treynolds_searching tr.treynolds_active input ,
180
+ .entry-edit.treynolds_searching tr.treynolds_active select ,
181
+ .entry-edit.treynolds_searching tr.treynolds_active textarea {
182
+ background-color: #fff !important;
183
+ }
184
+
185
+ .entry-edit.treynolds_searching tr.treynolds_active td:first-child{
186
+ border-top-left-radius: 12px;
187
+ border-bottom-left-radius: 12px;
188
+ }
189
+ .entry-edit.treynolds_searching tr.treynolds_active td:last-child{
190
+ border-top-right-radius: 12px;
191
+ border-bottom-right-radius: 12px;
192
+ min-width: 12px;
193
+ }
194
+ .entry-edit.treynolds_searching tr.treynolds_active.treynolds_top td:first-child{
195
+ border-bottom-left-radius: 0!important;
196
+ }
197
+ .entry-edit.treynolds_searching tr.treynolds_active.treynolds_top td:last-child{
198
+ border-bottom-right-radius: 0!important;
199
+ }
200
+ .entry-edit.treynolds_searching tr.treynolds_active.treynolds_bottom td:first-child{
201
+ border-top-left-radius: 0!important;
202
+ }
203
+ .entry-edit.treynolds_searching tr.treynolds_active.treynolds_bottom td:last-child{
204
+ border-top-right-radius: 0!important;
205
+ }